Cross-platform library for retrieving information on running processes and system utilization (CPU, memory, disks, network, sensors) in Python
—
The Process class is the core component of psutil for process management and monitoring. It represents individual system processes and provides comprehensive access to process information, resource usage, and control operations.
import psutil
# Current process
current = psutil.Process()
# Process by PID
p = psutil.Process(1234)
# Process using Popen (subprocess alternative)
p = psutil.Popen(['python', 'script.py']){ .api }
# Iterate over all processes
for proc in psutil.process_iter():
print(proc.pid, proc.name())
# Iterate with specific attributes (more efficient)
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent']):
print(proc.info)
# Process filtering
python_procs = [p for p in psutil.process_iter() if 'python' in p.name().lower()]{ .api }
p = psutil.Process()
# Process identification
pid = p.pid # Process ID
ppid = p.ppid() # Parent process ID
name = p.name() # Process name
exe = p.exe() # Executable path
cmdline = p.cmdline() # Command line arguments
environ = p.environ() # Environment variables{ .api }
# Process status
status = p.status() # Process status (running, sleeping, etc.)
is_running = p.is_running() # Check if process is running
create_time = p.create_time() # Process creation time
# Process relationships
parent = p.parent() # Parent process object
children = p.children() # List of child processes
children_recursive = p.children(recursive=True) # Include grandchildren{ .api }
# User information
username = p.username() # Process owner username
uids = p.uids() # Real, effective, saved user IDs
gids = p.gids() # Real, effective, saved group IDs
terminal = p.terminal() # Controlling terminal{ .api }
# CPU usage
cpu_percent = p.cpu_percent() # CPU usage percentage
cpu_percent_interval = p.cpu_percent(interval=1) # With measurement interval
cpu_times = p.cpu_times() # CPU times (user, system)
cpu_affinity = p.cpu_affinity() # CPU affinity mask
cpu_num = p.cpu_num() # Current CPU number{ .api }
# Memory usage
memory_info = p.memory_info() # RSS, VMS memory
memory_full_info = p.memory_full_info() # Extended memory info
memory_percent = p.memory_percent() # Memory usage percentage
# Memory mappings (Linux, FreeBSD, macOS)
if hasattr(p._proc, 'memory_maps'):
memory_maps = p.memory_maps() # Memory regions (grouped by default)
memory_maps_detailed = p.memory_maps(grouped=False) # Individual regions{ .api }
# I/O operations
io_counters = p.io_counters() # Read/write bytes and operations
num_ctx_switches = p.num_ctx_switches() # Context switches
num_fds = p.num_fds() # Number of file descriptors (Unix)
num_handles = p.num_handles() # Number of handles (Windows)
num_threads = p.num_threads() # Number of threads
# Thread details (platform-dependent availability)
if hasattr(p._proc, 'threads'):
threads = p.threads() # List of thread info namedtuples{ .api }
# Open files and connections
open_files = p.open_files() # List of open files
connections = p.connections() # Network connections
connections_all = p.connections(kind='all') # All connection types{ .api }
# Thread details (Linux, Windows, FreeBSD, macOS)
if hasattr(psutil.Process().__class__, 'threads'):
threads = p.threads() # Returns list of thread namedtuples
for thread in threads:
print(f"Thread ID: {thread.id}")
print(f"User time: {thread.user_time}")
print(f"System time: {thread.system_time}"){ .api }
# Process control
p.suspend() # Suspend process
p.resume() # Resume suspended process
p.terminate() # Terminate process (SIGTERM)
p.kill() # Kill process (SIGKILL)
# Wait for process termination
p.wait() # Wait indefinitely
p.wait(timeout=10) # Wait with timeout{ .api }
# Send signals (Unix)
import signal
p.send_signal(signal.SIGTERM) # Send specific signal
p.send_signal(signal.SIGUSR1) # Send custom signal{ .api }
# Linux only
if psutil.LINUX:
rlimit = p.rlimit(psutil.RLIMIT_NOFILE) # Resource limits
ionice = p.ionice() # I/O priority
cwd = p.cwd() # Current working directory
root = p.rlimit(psutil.RLIMIT_CORE) # Core dump size limit{ .api }
# Windows only
if psutil.WINDOWS:
nice = p.nice() # Process priority
ionice = p.ionice() # I/O priority class
num_handles = p.num_handles() # Windows handles{ .api }
# macOS only
if psutil.OSX:
nice = p.nice() # Process priority (nice value)
# Additional macOS-specific attributes available{ .api }
p1 = psutil.Process(1234)
p2 = psutil.Process(1234)
# Process equality
equal = (p1 == p2) # True if same PID
same_process = p1.is_running() and p2.is_running()
# Process hashing
process_set = {p1, p2} # Can use in sets/dicts{ .api }
# Access multiple attributes efficiently
attrs = p.as_dict(['pid', 'name', 'cpu_percent', 'memory_info'])
print(attrs)
# With error handling for individual attributes
attrs = p.as_dict(['pid', 'name'], ad_value='N/A') # Use default for access denied{ .api }
def print_process_tree(parent, indent=0):
"""Print process tree starting from parent."""
try:
print(' ' * indent + f"{parent.pid} {parent.name()}")
for child in parent.children():
print_process_tree(child, indent + 2)
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
# Print tree for process and all children
print_process_tree(psutil.Process()){ .api }
# Use oneshot() context manager for efficient multiple attribute access
p = psutil.Process()
# Without oneshot - each call makes separate system calls
name = p.name()
cpu_percent = p.cpu_percent()
memory_info = p.memory_info()
create_time = p.create_time()
# With oneshot - single system call fetches multiple attributes
with p.oneshot():
name = p.name() # Fetches and caches multiple attributes
cpu_percent = p.cpu_percent() # Returns cached value
memory_info = p.memory_info() # Returns cached value
create_time = p.create_time() # Returns cached value
# Especially beneficial for process monitoring loops
def monitor_processes():
"""Efficiently monitor multiple processes."""
for proc in psutil.process_iter():
try:
with proc.oneshot():
# All these calls use cached data from single syscall
info = {
'pid': proc.pid,
'name': proc.name(),
'cpu_percent': proc.cpu_percent(),
'memory_rss': proc.memory_info().rss,
'status': proc.status(),
'create_time': proc.create_time()
}
print(info)
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass{ .api }
try:
p = psutil.Process(1234)
print(f"Process: {p.name()}")
print(f"CPU: {p.cpu_percent()}")
print(f"Memory: {p.memory_info()}")
except psutil.NoSuchProcess:
print("Process not found or terminated")
except psutil.AccessDenied:
print("Permission denied - may need elevated privileges")
except psutil.ZombieProcess:
print("Process exists but is zombie state")
except psutil.TimeoutExpired:
print("Operation timed out"){ .api }
import time
def monitor_process(pid, duration=60):
"""Monitor process for specified duration."""
try:
p = psutil.Process(pid)
start_time = time.time()
while time.time() - start_time < duration:
if not p.is_running():
print("Process terminated")
break
cpu = p.cpu_percent(interval=1)
memory = p.memory_info()
print(f"CPU: {cpu:5.1f}% | Memory: {memory.rss / 1024**2:6.1f} MB")
except psutil.NoSuchProcess:
print("Process not found"){ .api }
def get_process_stats(proc):
"""Get comprehensive process statistics."""
try:
return {
'pid': proc.pid,
'name': proc.name(),
'status': proc.status(),
'cpu_percent': proc.cpu_percent(),
'memory_rss': proc.memory_info().rss,
'memory_vms': proc.memory_info().vms,
'num_threads': proc.num_threads(),
'create_time': proc.create_time(),
'username': proc.username()
}
except (psutil.NoSuchProcess, psutil.AccessDenied) as e:
return {'error': str(e)}
# Collect stats for all processes
all_stats = []
for proc in psutil.process_iter():
stats = get_process_stats(proc)
if 'error' not in stats:
all_stats.append(stats){ .api }
process_iter() with attribute lists for efficient bulk operationsinterval parameter with cpu_percent() for accurate measurementsInstall with Tessl CLI
npx tessl i tessl/pypi-psutil