Process management is an important part of working with operating systems, and Python makes it easy using the psutil
library. This powerful tool lets you access and control system processes directly by their Process IDs, or PIDs. With psutil
, you can find running processes, read detailed information about them, and even manage their state—like suspending, resuming, or terminating them.
In this article, you will learn how to use psutil
to work with processes by PID. We’ll cover how to access a process using its PID, gather useful information about it, control its execution, and monitor its status. By the end, you’ll have a clear understanding of how to manage processes programmatically with Python.
Setting Up: Installing and Importing psutil
Before you start managing processes, you need to install the psutil
library. You can easily install it using pip with the following command:
pip install psutil
Once installed, import psutil
in your Python script to access its functions. To confirm everything is set up correctly, you can print the version of psutil
installed:
import psutil
print(f"psutil version: {psutil.__version__}")
This simple step ensures your environment is ready to work with system processes using psutil
.
Accessing a Process by PID
To interact with a process using psutil
, you start by creating a Process
object with its PID. This allows you to inspect and control the process. If the PID doesn’t exist—maybe because the process ended—you’ll get a psutil.NoSuchProcess
exception, so it’s good to catch that.
Here’s an example that accesses the currently running Python process using its own PID:
import os
import psutil
pid = os.getpid() # Get the PID of the current process
try:
process = psutil.Process(pid) # Create a Process object
print(f"Accessed process with PID {pid}: {process.name()}")
except psutil.NoSuchProcess:
print(f"No process found with PID {pid}")
This prints the name of the running Python script’s process. If something goes wrong—like the process ending before it’s accessed—NoSuchProcess
will handle it gracefully.
Reading Basic Process Information
Once you have a Process
object using its PID, you can easily access several useful details about it. psutil
lets you check the process name, current status (like running or sleeping), when it started, how much CPU it’s using, and how much memory it consumes.
Here’s a full example that prints these details:
import os
import psutil
import time
pid = os.getpid()
process = psutil.Process(pid)
print(f"Name: {process.name()}")
print(f"Status: {process.status()}")
print(f"Created: {time.ctime(process.create_time())}")
print(f"CPU usage: {process.cpu_percent(interval=1)}%")
print(f"Memory usage: {process.memory_info().rss / (1024 * 1024):.2f} MB")
In this code, we get the process info for the current Python script. The cpu_percent(interval=1)
call waits for one second to calculate an accurate CPU usage percentage. The memory usage is printed in megabytes, converted from bytes. This helps you quickly inspect how a process is behaving.
Listing Child Processes
A process can have other processes that it started—these are called child processes. With psutil
, you can list them using the .children()
method on a Process
object. This is useful when managing applications that spawn helper processes, like servers or background workers.
Here’s a short example that finds and prints all children of the current process:
import os
import psutil
pid = os.getpid()
process = psutil.Process(pid)
children = process.children()
for child in children:
print(f"Child PID: {child.pid}, Name: {child.name()}")
If your process doesn’t create any children, this list will simply be empty. But in programs that spawn subprocesses (for tasks, workers, etc.), this is a handy way to keep track of what’s running underneath.
Sending Signals and Managing Process State
Once you have a Process
object using psutil
, you can control it directly. Python makes it easy to send standard operating system signals, such as suspend, resume, terminate, or even force-kill a process. This is helpful for scripting task control, managing background jobs, or building your own task manager.
Here’s an example where we create a dummy process (sleep 10
) and then manipulate its state using psutil
:
import subprocess
import time
import psutil
# Start a dummy process that sleeps for 10 seconds
proc = subprocess.Popen(['sleep', '10'])
p = psutil.Process(proc.pid)
# Suspend the process
print(f"Suspending process {p.pid}")
p.suspend()
time.sleep(2)
# Resume the process
print(f"Resuming process {p.pid}")
p.resume()
time.sleep(2)
# Terminate the process
print(f"Terminating process {p.pid}")
p.terminate()
This code launches a new process, pauses it with suspend()
, waits, then resumes it with resume()
. Finally, it calls terminate()
to stop it early. If you run this script, you’ll see the process get controlled step-by-step, just like a basic task controller.
Fix for Windows
Oh, and I tried running this on Windows—and it didn’t work. I got this error: FileNotFoundError: [WinError 2] The system cannot find the file specified
. That’s because the command ['sleep', '10']
works fine on Unix systems like Linux or macOS, but it doesn’t exist on Windows. There’s no built-in sleep
executable in the Windows command line like there is in Unix-based systems.
To fix this and still create a dummy process that just sleeps for a while, we can use Python itself. Instead of trying to run an external command, we launch a new Python process and tell it to run time.sleep(10)
directly. This way, the command works no matter what operating system you’re using.
Here’s the updated version of the code that works on Windows:
import subprocess
import time
import psutil
import sys
# Start a dummy Python process that sleeps for 10 seconds
proc = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(10)"])
p = psutil.Process(proc.pid)
print(f"Suspending process {p.pid}")
p.suspend()
time.sleep(2)
print(f"Resuming process {p.pid}")
p.resume()
time.sleep(2)
print(f"Terminating process {p.pid}")
p.terminate()
This version uses sys.executable
to make sure we’re calling the same Python interpreter that’s running the script. The -c
option lets us run a one-liner Python command in the new process, in this case import time; time.sleep(10)
. After that, we wrap the process with psutil.Process
so we can pause it with suspend()
, resume it with resume()
, and finally stop it with terminate()
.
This small change makes the code work across Windows, Linux, and macOS, and keeps the example fun and reliable on any system.
Waiting for Process Completion
Sometimes you want to wait for a process to finish before continuing your program. With psutil
, you can do this using the .wait()
method on a Process
object. This will block your code until the process has finished, then return the exit code when it’s done.
Let’s look at a simple example. We’ll start a dummy process that just sleeps for a few seconds, then wait for it to complete and print the result. Keep in mind, if you’re on Windows, the 'sleep'
command won’t work—so we’ll use Python itself to run the sleep command cross-platform.
import subprocess
import time
import psutil
import sys
# Start a Python process that just sleeps for 3 seconds
proc = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(3)"])
p = psutil.Process(proc.pid)
print("Waiting for process to finish...")
exit_code = p.wait()
print(f"Process exited with code {exit_code}")
In this code, subprocess.Popen
starts a new Python process that pauses for three seconds. We wrap it using psutil.Process
so we can manage it. The call to p.wait()
blocks until the process ends, and then we print its exit code. This is a simple way to synchronize with other processes when you need to make sure they’ve completed before moving on.
Checking if a Process is Running
Sometimes you just want to know whether a process is still alive or has already exited. psutil
makes this easy with the .is_running()
method. It returns True
if the process is currently active and False
if it has finished or no longer exists.
Here’s a small example that starts a short-lived process, checks if it’s running right after it starts, waits for it to finish, and then checks again:
import subprocess
import time
import psutil
import sys
# Start a short-lived Python sleep process
proc = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(2)"])
p = psutil.Process(proc.pid)
print(f"Process {p.pid} is running:", p.is_running())
print("Waiting for it to finish...")
proc.wait()
print(f"Process {p.pid} is running after wait:", p.is_running())
In this script, we launch a process that sleeps for 2 seconds. Immediately after starting, we check if it’s running—it should return True
. After we call wait()
to block until the process finishes, we check again. This time, .is_running()
should return False
, showing that the process has exited. This method is a quick and effective way to monitor process activity.
Fun Example: Process Watchdog
Let’s build a fun little watchdog—a script that watches another process by its PID and keeps reporting its CPU and memory usage every second until that process exits. This is a simple but powerful way to see how psutil
can be used to monitor the life and health of a running process.
In this example, we’ll first launch a short-lived Python process that sleeps for a few seconds. Then, we’ll start our watchdog that monitors it in real time.
import subprocess
import psutil
import time
import sys
# Start a short-lived process (simulate work)
target_proc = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(5)"])
watched_pid = target_proc.pid
print(f"Watching process with PID: {watched_pid}")
try:
proc = psutil.Process(watched_pid)
except psutil.NoSuchProcess:
print("Process no longer exists.")
sys.exit(1)
# Watchdog loop
while proc.is_running():
cpu = proc.cpu_percent(interval=0.5)
mem = proc.memory_info().rss / (1024 * 1024)
print(f"[{time.strftime('%X')}] CPU: {cpu:.1f}% | Memory: {mem:.2f} MB")
time.sleep(1)
print("Process has exited. Watchdog stopping.")
In this script, psutil.Process()
wraps the target process using its PID. Inside the loop, cpu_percent(interval=0.5)
measures CPU usage over half a second, and memory_info().rss
shows resident memory in megabytes. We pause for a second between checks using time.sleep(1)
, and the loop exits cleanly once the target process has ended.
The output updates like a live status log, making it a fun and practical way to observe what a process is doing in real time.
Conclusion
Using psutil
, you can easily access and manage system processes by their PIDs right from Python. This article showed you how to read detailed information about processes, control their state by suspending or terminating them, send signals, and even monitor their resource use in real time. With these tools, you have the power to interact with and manage processes programmatically, opening up many possibilities for automation and system control. Give these techniques a try to explore how you can integrate process management smoothly into your Python projects.