Skip to main content

How to Capture System Metrics Programmatically in Python

Monitoring system metrics (such as CPU usage, memory consumption, disk I/O, and network traffic) is essential for building health checks, performance profilers, and dashboarding tools. While operating systems provide command-line tools like top or Task Manager, accessing this data programmatically allows developers to build custom alerting systems and automated resource managers.

This guide explains how to capture these metrics in Python using the cross-platform psutil library.

Setting Up the Environment

Python does not have built-in modules that cover deep system metrics across all operating systems. The industry standard library for this task is psutil (process and system utilities).

Installation:

pip install psutil

Method 1: Capturing CPU and Memory Metrics

The two most critical health indicators are the processor load and RAM availability.

CPU Metrics

psutil.cpu_percent() calculates the current CPU utilization as a percentage. It compares system clock ticks between intervals.

note

The interval argument is crucial. If set to 0 or None, it returns the usage since the last call immediately (which is often 0.0). If set to 1, the function blocks for 1 second to calculate the average usage over that second.

Memory Metrics

psutil.virtual_memory() returns an object containing statistics about system memory usage.

import psutil

# ✅ Solution: CPU and Memory Snapshot
def get_core_metrics():
# 1. CPU Usage
# interval=1 blocks for 1 second to measure usage
cpu_usage = psutil.cpu_percent(interval=1)

# 2. CPU Frequency (Current, Min, Max)
# May require root/admin privileges on some OS
cpu_freq = psutil.cpu_freq()

# 3. Memory Usage
ram = psutil.virtual_memory()

print(f"--- System Snapshot ---")
print(f"CPU Usage: {cpu_usage}%")
print(f"CPU Frequency: {cpu_freq.current:.2f} Mhz")
print(f"Total RAM: {ram.total / (1024**3):.2f} GB")
print(f"Available RAM: {ram.available / (1024**3):.2f} GB")
print(f"RAM Usage: {ram.percent}%")

if __name__ == "__main__":
get_core_metrics()

Output:

--- System Snapshot ---
CPU Usage: 12.5%
CPU Frequency: 3600.00 Mhz
Total RAM: 16.00 GB
Available RAM: 8.45 GB
RAM Usage: 47.2%

Method 2: Monitoring Disk and Network I/O

Disk and network metrics are vital for identifying I/O bottlenecks.

Disk Usage

psutil.disk_usage(path) return usage statistics for the partition containing the given path.

Network Stats

psutil.net_io_counters() provides total bytes sent and received. Since these are cumulative counters (total bytes since boot), calculating the current speed requires taking two snapshots and finding the difference.

import psutil
import time

def get_io_metrics():
# 1. Disk Usage (Root partition)
# On Windows, use "C:\\" instead of "/"
disk = psutil.disk_usage('/')

print(f"--- Disk & Network ---")
print(f"Disk Total: {disk.total / (1024**3):.2f} GB")
print(f"Disk Used: {disk.percent}%")

# 2. Network Speed Calculation
print("Calculating network speed (sampling for 1 second)...")
net1 = psutil.net_io_counters()
time.sleep(1)
net2 = psutil.net_io_counters()

# Difference in bytes
bytes_sent = net2.bytes_sent - net1.bytes_sent
bytes_recv = net2.bytes_recv - net1.bytes_recv

print(f"Upload Speed: {bytes_sent / 1024:.2f} KB/s")
print(f"Download Speed: {bytes_recv / 1024:.2f} KB/s")

if __name__ == "__main__":
get_io_metrics()

Output:

--- Disk & Network ---
Disk Total: 465.63 GB
Disk Used: 65.4%
Calculating network speed (sampling for 1 second)...
Upload Speed: 12.05 KB/s
Download Speed: 340.10 KB/s

Method 3: Building a Continuous Monitor

For real-world applications, you usually need to collect metrics periodically and output them in a structured format (like JSON) for logging or dashboards.

import psutil
import time
import json
from datetime import datetime

def monitor_system(interval=5):
print(f"Starting monitoring (Ctrl+C to stop)... Interval: {interval}s")

try:
while True:
# Gather metrics
metrics = {
"timestamp": datetime.now().isoformat(),
"cpu_percent": psutil.cpu_percent(interval=None),
"memory_percent": psutil.virtual_memory().percent,
"disk_percent": psutil.disk_usage('/').percent
}

# Output as JSON line
print(json.dumps(metrics))

# Wait for next cycle
time.sleep(interval)

except KeyboardInterrupt:
print("\nMonitoring stopped.")

if __name__ == "__main__":
# Initialize CPU counter (first call always returns 0.0)
psutil.cpu_percent(interval=None)
monitor_system()
warning

Permission Errors: Accessing detailed process information or specific system counters might require Administrator (Windows) or Root (Linux) privileges. If your script crashes with AccessDenied, try running the terminal as an administrator.

Conclusion

Programmatic system monitoring in Python is straightforward with psutil:

  1. CPU: Use psutil.cpu_percent(interval=1) to measure load over time.
  2. Memory: Use psutil.virtual_memory() to check RAM limits.
  3. Disk: Use psutil.disk_usage('/') to prevent storage overflow.
  4. Network: Calculate the difference between psutil.net_io_counters() snapshots to determine speed.