This Python script provides a comprehensive real-time system resource monitoring solution that tracks CPU usage, memory consumption, and disk I/O operations. It displays current metrics in the terminal and stores historical data for later analysis. The script also generates a visual graph of resource usage over time, making it useful for system administrators, developers, and performance analysts.
import psutil
import time
import matplotlib.pyplot as plt
from collections import deque
import threading
from datetime import datetime
class SystemResourceMonitor:
def __init__(self, max_history=300, update_interval=1):
self.max_history = max_history
self.update_interval = update_interval
self.cpu_usage = deque(maxlen=max_history)
self.memory_usage = deque(maxlen=max_history)
self.disk_read = deque(maxlen=max_history)
self.disk_write = deque(maxlen=max_history)
self.timestamps = deque(maxlen=max_history)
self.disk_last_read = 0
self.disk_last_write = 0
self.monitoring = False
self.lock = threading.Lock()
def get_disk_io(self):
"""Get disk I/O statistics"""
disk_io = psutil.disk_io_counters()
return disk_io.read_bytes, disk_io.write_bytes
def start_monitoring(self):
"""Start monitoring system resources"""
self.monitoring = True
print("Starting system resource monitoring...")
print("Press Ctrl+C to stop and view results")
# Get initial disk I/O values
self.disk_last_read, self.disk_last_write = self.get_disk_io()
while self.monitoring:
try:
# Get CPU usage
cpu = psutil.cpu_percent(interval=1)
# Get memory usage
memory = psutil.virtual_memory().percent
# Get disk I/O (calculated as bytes per second)
current_read, current_write = self.get_disk_io()
disk_read_speed = (current_read - self.disk_last_read) / self.update_interval
disk_write_speed = (current_write - self.disk_last_write) / self.update_interval
self.disk_last_read, self.disk_last_write = current_read, current_write
# Get timestamp
timestamp = datetime.now()
# Store data with thread safety
with self.lock:
self.cpu_usage.append(cpu)
self.memory_usage.append(memory)
self.disk_read.append(disk_read_speed)
self.disk_write.append(disk_write_speed)
self.timestamps.append(timestamp)
# Clear screen and update display
print("\033[2J\033[H", end="") # Clear screen
self.display_current_metrics()
time.sleep(self.update_interval)
except KeyboardInterrupt:
self.stop_monitoring()
break
def stop_monitoring(self):
"""Stop monitoring system resources"""
self.monitoring = False
print("\nMonitoring stopped. Generating visualization...")
def display_current_metrics(self):
"""Display current metrics in a formatted way"""
print("=" * 50)
print("REAL-TIME SYSTEM RESOURCE MONITOR")
print("=" * 50)
if self.cpu_usage:
cpu = self.cpu_usage[-1]
memory = self.memory_usage[-1]
disk_read = self.disk_read[-1]
disk_write = self.disk_write[-1]
# CPU usage visualization
print(f"CPU USAGE: {cpu:5.1f}% ", end="")
print("[" + "█" * int(cpu/2) + " " * (50 - int(cpu/2)) + "]")
# Memory usage visualization
print(f"MEMORY: {memory:5.1f}% ", end="")
print("[" + "█" * int(memory/2) + " " * (50 - int(memory/2)) + "]")
# Disk I/O
print(f"DISK READ: {disk_read/1024/1024:8.2f} MB/s")
print(f"DISK WRITE: {disk_write/1024/1024:8.2f} MB/s")
# Timestamp
print(f"\nLast updated: {datetime.now().strftime('%H:%M:%S')}")
print("\nPress Ctrl+C to stop and view results")
def save_data(self, filename="system_monitor_data.csv"):
"""Save collected data to CSV file"""
with self.lock:
with open(filename, 'w') as f:
f.write("Timestamp,CPU Usage (%),Memory Usage (%),Disk Read (MB/s),Disk Write (MB/s)\n")
for i, timestamp in enumerate(self.timestamps):
cpu = self.cpu_usage[i] if i < len(self.cpu_usage) else 0
memory = self.memory_usage[i] if i < len(self.memory_usage) else 0
read = self.disk_read[i] / 1024 / 1024 if i < len(self.disk_read) else 0
write = self.disk_write[i] / 1024 / 1024 if i < len(self.disk_write) else 0
f.write(f"{timestamp},{cpu:.2f},{memory:.2f},{read:.2f},{write:.2f}\n")
print(f"Data saved to {filename}")
def plot_resources(self):
"""Plot resource usage over time"""
with self.lock:
if not self.timestamps:
print("No data to plot")
return
# Create time series
times = [t for t in self.timestamps]
cpu_data = [cpu for cpu in self.cpu_usage]
memory_data = [memory for memory in self.memory_usage]
disk_read_data = [read / 1024 / 1024 for read in self.disk_read]
disk_write_data = [write / 1024 / 1024 for write in self.disk_write]
# Create plots
plt.style.use('seaborn-v0_8')
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(12, 10))
# CPU usage
ax1.plot(times, cpu_data, label='CPU Usage %', color='tab:red', linewidth=1.5)
ax1.set_title('CPU Usage Over Time')
ax1.set_ylabel('Percentage (%)')
ax1.set_ylim(0, 100)
ax1.grid(True, alpha=0.3)
ax1.legend()
# Memory usage
ax2.plot(times, memory_data, label='Memory Usage %', color='tab:blue', linewidth=1.5)
ax2.set_title('Memory Usage Over Time')
ax2.set_ylabel('Percentage (%)')
ax2.set_ylim(0, 100)
ax2.grid(True, alpha=0.3)
ax2.legend()
# Disk I/O
ax3.plot(times, disk_read_data, label='Disk Read (MB/s)', color='tab:green', linewidth=1.5)
ax3.plot(times, disk_write_data, label='Disk Write (MB/s)', color='tab:orange', linewidth=1.5)
ax3.set_title('Disk I/O Performance')
ax3.set_ylabel('Speed (MB/s)')
ax3.set_xlabel('Time')
ax3.grid(True, alpha=0.3)
ax3.legend()
# Format time on x-axis
fig.autofmt_xdate()
plt.tight_layout()
plt.show()
# Example usage
if __name__ == "__main__":
# Create monitor instance
monitor = SystemResourceMonitor(max_history=500, update_interval=1)
try:
# Start monitoring
monitor.start_monitoring()
except Exception as e:
print(f"Error: {e}")
# Save data and plot
monitor.save_data("system_resources.csv")
monitor.plot_resources()
pip install psutil matplotlib
python system_monitor.py
Ctrl+C
to stop the monitoring and generate the visualizationThis system resource monitor uses Python’s psutil
library to collect system statistics, including:
The monitor provides real-time visual feedback in the terminal with a bar chart representation for CPU and memory usage. It also calculates and stores historical data for performance analysis.
The script runs in a continuous loop, collecting data at the specified interval (default: 1 second). It stores historical data with a configurable maximum size (default: 300 entries) to prevent memory overflow.
Upon stopping the monitoring with Ctrl+C
, the script creates two visual representations:
This script is useful for:
The real-time visualization provides immediate insights into system performance, while the historical data and plot capabilities allow for deeper analysis of resource usage patterns.