Hello there, coders! Today, we’re going to build a dynamic command-line application that visualizes your PC’s performance metrics in real-time (like this one). If that sounds exciting, let’s dive right in!
Table of contents
Open Table of contents
What are we building?
We’re crafting a Python application that pulls key performance metrics such as CPU usage, memory usage, disk usage, and more. The application will then display these metrics in a visually appealing, easy-to-read format in the command line. This is a useful tool for anyone looking to get instant insights into their computer’s performance.
Tools we need
For this project, we’ll be using Python and a couple of libraries - psutil
for retrieving system information, rich
for creating an attractive console interface, and finally asciichartpy
for a generating an ASCII based chart.
psutil
: A Python cross-platform library used to access system details and process utilities.rich
: A Python library for rich text and beautiful formatting in the terminal.asciichartpy
: A python library for generating formatted ASCII charts on the terminal.
Breaking down the project
Our application has two main parts:
- Fetching system data using
psutil
. - Displaying the data using
rich
(andasciichartpy
to display the chart).
Fetching system data
To fetch system data, we’ll use the psutil
library, which can gather information about CPU, memory, disks, network, sensors, and processes in our system. In layman’s terms, it’s like our personal system inspector.
Displaying the data
For the display, we’re using the rich
library. rich
can create text with styles, colors, and even tables, making our command line look like a work of art!
Implementation
Installing libraries
First, let’s install our necessary libraries with pip:
pip install psutil rich asciichartpy
Then we can start building our project. We’ll divide the code into four parts: utils.py
for fetching data, charts.py
for creating charts, tables.py
for creating tables, and main.py
for running our application.
Fetching system stats
In utils.py
, we’ll define a function get_system_info()
to gather system statistics:
# utils.py
import psutil
import time
def get_system_info():
cpu_percent = psutil.cpu_percent()
memory_info = psutil.virtual_memory()
disk_info = psutil.disk_usage("/")
uptime = time.time() - psutil.boot_time()
network_info = psutil.net_io_counters()
processes = len(psutil.pids())
swap_info = psutil.swap_memory()
return (
cpu_percent,
memory_info,
disk_info,
uptime,
network_info,
processes,
swap_info,
)
Creating the chart
In charts.py
, we’ll create a function to generate our CPU chart:
# charts.py
from rich.text import Text
from asciichartpy import plot
def get_cpu_chart(cpu_data):
return Text(plot(list(cpu_data), {"height": 18}), style="cyan")
Creating the tables
In tables.py
, we’ll create functions to generate different tables that display different PC stats:
# tables.py
from rich.table import Table
def get_system_table(metric, percent, total, used, name, color):
table = Table(expand=True)
table.add_column("Metric", justify="center", style=f"{color}", no_wrap=True)
table.add_column("Value", justify="center", style=f"{color}", no_wrap=True)
table.add_row(f"{name} Usage", f"{percent}%")
table.add_row("Total", f"{total / (1024.0 ** 3):.2f} GB")
table.add_row("Used", f"{used / (1024.0 ** 3):.2f} GB")
table.add_row("Usage Percentage", f"{percent}%")
return table
def get_uptime_table(uptime):
table = Table(expand=True)
table.add_column(
"Uptime (in seconds)", style="purple", justify="center", no_wrap=True
)
table.add_row(f"{uptime:.2f}")
return table
def get_network_table(network_info):
table = Table(expand=True)
table.add_column("Sent (GB)", style="red", justify="center", no_wrap=True)
table.add_column("Received (GB)", style="red", justify="center", no_wrap=True)
table.add_row(
f"{network_info.bytes_sent / (1024.0 ** 3):.2f}",
f"{network_info.bytes_recv / (1024.0 ** 3):.2f}",
)
return table
def get_processes_table(processes):
table = Table(expand=True)
table.add_column("Running processes", style="green", justify="center", no_wrap=True)
table.add_row(f"{processes}")
return table
def get_swap_table(swap_info):
table = Table(expand=True)
table.add_column("Total (GB)", style="yellow", justify="center", no_wrap=True)
table.add_column("Used (GB)", style="yellow", justify="center", no_wrap=True)
table.add_row(
f"{swap_info.total / (1024.0 ** 3):.2f}",
f"{swap_info.used / (1024.0 ** 3):.2f}",
)
return table
Creating the live “canvas” to display everything
Finally, in main.py
, we’ll bring everything together:
# main.py
import time
from collections import deque
from utils import get_system_info
from tables import (
get_system_table,
get_swap_table,
get_network_table,
get_processes_table,
get_uptime_table,
)
from charts import get_cpu_chart
from rich.console import Console
from rich.layout import Layout
from rich.live import Live
from rich.panel import Panel
console = Console()
layout = Layout()
cpu_data = deque(maxlen=60)
# Define layout structure
layout.split_column(Layout(name="upper"), Layout(name="middle"), Layout(name="lower"))
layout["upper"].split_row(
Layout(name="cpu"), Layout(name="memory"), Layout(name="disk")
)
layout["middle"].split_row(
Layout(name="uptime"),
Layout(name="network"),
Layout(name="processes"),
Layout(name="swap"),
)
def main():
with Live(
console=console, refresh_per_second=2, screen=True
) as live: # use screen=True for full screen
while True:
(
cpu_percent,
memory_info,
disk_info,
uptime,
network_info,
processes,
swap_info,
) = get_system_info()
cpu_data.append(cpu_percent)
cpu_table = get_system_table(
cpu_percent,
cpu_percent,
memory_info.total,
memory_info.used,
"CPU",
"cyan",
)
memory_table = get_system_table(
memory_info.percent,
memory_info.percent,
memory_info.total,
memory_info.used,
"Memory",
"green",
)
disk_table = get_system_table(
disk_info.percent,
disk_info.percent,
disk_info.total,
disk_info.used,
"Disk",
"yellow",
)
uptime_table = get_uptime_table(uptime)
network_table = get_network_table(network_info)
processes_table = get_processes_table(processes)
swap_table = get_swap_table(swap_info)
# Define layout structure
layout.split_column(
Layout(name="upper"),
Layout(name="middle"),
Layout(
Panel(
get_cpu_chart(cpu_data),
title="CPU Usage Graph",
style="bold cyan",
),
ratio=2,
),
)
layout["upper"].split_row(
Layout(Panel(cpu_table, title="CPU Usage", style="bold cyan")),
Layout(Panel(memory_table, title="Memory Usage", style="bold green")),
Layout(Panel(disk_table, title="Disk Usage", style="bold yellow")),
)
layout["middle"].split_row(
Layout(Panel(uptime_table, title="Uptime", style="bold purple")),
Layout(Panel(network_table, title="Network Usage", style="bold red")),
Layout(Panel(processes_table, title="Processes", style="bold green")),
Layout(Panel(swap_table, title="Saw Memory", style="bold yellow")),
)
live.update(layout)
time.sleep(1)
if __name__ == "__main__":
main()
Now you can run python main.py
on your terminal and checkout your magnificent creation!
And there you have it, a Python command-line application that provides real-time visualization of your computer’s performance metrics.
Notes
In main.py
, we use a deque
to store the last 60 seconds of CPU usage data. We then use asciichartpy
’s plot
function to create a line graph of this data using the get_cpu_chart
function we created inside charts.py
. This graph is then updated every second in the Live
context from rich
.
Wrapping Up
This simple yet powerful tool provides valuable insights into your computer’s health. It’s a great project to sharpen your Python skills and to learn about system statistics and console-based applications.
Happy coding!
References
- psutils docs: https://psutil.readthedocs.io/en/latest/
- rich docs: https://rich.readthedocs.io/en/stable/
- asciichartpy: https://github.com/kroitor/asciichart