Psutil Tutorial: Tracking System Utilisation and Processes

Written by

in

psutil (Python System and Process Utilities) is a powerful cross-platform library used to retrieve information on running processes and system utilization (CPU, memory, disks, network, and sensors). It acts as a standardized Python wrapper for low-level operating system APIs, effectively replicating the functionality of classic command-line utilities like ps, top, lsof, netstat, and free across Linux, Windows, macOS, and BSD. Core Components of psutil

The library is broadly split into two primary areas of operational focus: System-wide Metrics and Process Management. 1. System Resource Monitoring

psutil allows you to monitor global hardware states directly from your code, which is vital for building internal diagnostics dashboards, server management tools, and auto-scaling agents.

import psutil # Get overall CPU utilization and per-core details print(f”Overall CPU: {psutil.cpu_percent(interval=1)}%“) print(f”Per-Core CPU: {psutil.cpu_percent(percpu=True)}“) # Extract virtual memory (RAM) allocation mem = psutil.virtual_memory() print(f”Available RAM: {mem.available / (10243):.2f} GB”) # Check disk space allocations and network I/O activity print(f”Disk Free: {psutil.disk_usage(‘/’).free / (10243):.2f} GB”) print(f”Network Sent/Recv: {psutil.net_io_counters().bytes_sent} / {psutil.net_io_counters().bytes_recv}“) Use code with caution. 2. Fine-Grained Process Architecture

The heart of advanced process management lies in the psutil.Process(pid) class, which targets individual execution trees. It provides granular insights into the security, networking, and filesystem footprint of any running process:

pid = 1234 # Example Target Process ID proc = psutil.Process(pid) print(f”Name: {proc.name()}“) print(f”Status: {proc.status()}“) print(f”Owner: {proc.username()}“) print(f”Memory RSS: {proc.memory_info().rss / (10242):.2f} MB”) print(f”Open Files: {proc.open_files()}“) print(f”Network Connections: {proc.connections()}“) Use code with caution. Advanced Process Management Patterns

Go beyond basic tracking with these highly useful production patterns for resource control, life-cycle automation, and filtering. High-Performance Process Iteration

Iterating over thousands of processes using a naive loop can trigger massive CPU overhead because Python must make repeated system calls for every single attribute. Use psutil.process_iter() bundled with the attrs parameter to drastically optimize your execution speed.

# Efficiently search and grab specific fields in a single optimized scan for proc in psutil.process_iter(attrs=[‘pid’, ‘name’, ‘username’]): try: if “python” in proc.info[‘name’].lower(): print(f”PID: {proc.info[‘pid’]} | User: {proc.info[‘username’]}“) except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): continue Use code with caution. Handling Process Lifecycles and Inter-Process Signals

You can dynamically pause, resume, or terminate tasks based on environmental events. This helps manage worker loops, clean up hanging child processes, or throttle active processing when resources are thin.

try: target_proc = psutil.Process(5678) # Pause execution state (SIGSTOP equivalent) target_proc.suspend() # Resume execution state (SIGCONT equivalent) target_proc.resume() # Graceful exit signal (SIGTERM) target_proc.terminate() # Forceful structural kill (SIGKILL) target_proc.kill() except psutil.NoSuchProcess: print(“The targeted process has already closed or never existed.”) Use code with caution. Managing Full Child Process Trees

When an application spins off complex sub-processes, killing the main parent often creates orphaned “zombie” operations that stay trapped in system memory. Below is the standard production pattern used to safely bring down a parent along with its entire downstream dependency tree:

def terminate_process_tree(parent_pid): try: parent = psutil.Process(parent_pid) # Gather all structural descendants recursively children = parent.children(recursive=True) # Terminate all target child structures first for child in children: child.terminate() # Terminate the primary root parent process parent.terminate() # Block and wait up to 3 seconds for successful teardown gone, alive = psutil.wait_procs(children + [parent], timeout=3) # Forcefully wipe any stubborn lingering processes for survivor in alive: survivor.kill() except psutil.NoSuchProcess: pass Use code with caution. Production Exceptions to Catch

When operating at an advanced level with OS-level processes, your code will frequently collide with kernel protection bounds. You must wrap your routines with proper error handling:

psutil.NoSuchProcess: Thrown if a process terminates in the brief window between when you query its PID and when you attempt to interact with it.

psutil.AccessDenied: Occurs when trying to query or control high-privilege system tasks or processes owned by another user system account.

psutil.ZombieProcess: Occurs when a process is technically dead but its parent has not yet read its exit status, leaving its entry in the process table.

If you want to tailor this further to your environment, tell me:

What Operating System (Linux, Windows, macOS) are you deploying this on?

Are you looking to build a monitoring dashboard, an automated script runner, or a resource limiter?

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *