Last modified: Feb 19, 2026 By Alexander Williams

Capture Command Output with Python Subprocess

Python's subprocess module is a powerful tool. It lets you run external commands from your Python scripts. A common task is capturing the output of these commands. This guide explains how to do it effectively.

Why Use Subprocess to Capture Output?

You might need to run a system command. You may need to process its result within your Python program. Manually running commands is not scalable. The subprocess module automates this interaction.

It is essential for scripting and automation tasks. You can capture text, error messages, and return codes. This data can then be logged, analyzed, or used to make decisions in your code.

The Core Function: subprocess.run()

The modern way to use the module is with subprocess.run(). This function runs a command and waits for it to complete. It returns a CompletedProcess object containing all results.

To capture output, you use the capture_output=True argument. This tells Python to grab anything the command prints to stdout and stderr.


import subprocess

# Run the 'ls' command and capture its output
result = subprocess.run(['ls', '-la'], capture_output=True, text=True)

print("Return Code:", result.returncode)
print("Standard Output:", result.stdout)
print("Standard Error:", result.stderr)
    

Return Code: 0
Standard Output: total 32
drwxr-xr-x  7 user  staff   224 Jan 10 10:00 .
drwxr-xr-x  9 user  staff   288 Jan  9 14:00 ..
-rw-r--r--  1 user  staff   450 Jan 10 09:55 script.py
Standard Error:
    

In this example, text=True is crucial. It ensures the output is returned as a string, not bytes. The result.stdout attribute holds the captured standard output.

Handling Standard Output and Error Separately

Commands can write to two streams: stdout for normal output and stderr for errors. It's good practice to capture them separately. This allows for better error handling and logging.

You can access them via result.stdout and result.stderr. Checking the returncode is also vital. A non-zero code usually indicates the command failed.


import subprocess

# Run a command that might produce an error
result = subprocess.run(['grep', 'python', 'nonexistent_file.txt'], capture_output=True, text=True)

if result.returncode != 0:
    print("Command failed!")
    print("Error message:", result.stderr)
else:
    print("Command succeeded.")
    print("Output:", result.stdout)
    

Command failed!
Error message: grep: nonexistent_file.txt: No such file or directory
    

Using subprocess.Popen for Advanced Control

For more complex scenarios, like real-time output processing, use subprocess.Popen. It offers finer control but is more complex than run().

You can read output as it's generated. This is useful for long-running commands. You can interact with the process while it's still alive.


import subprocess

# Using Popen to read output line by line
process = subprocess.Popen(['ping', '-c', '3', 'google.com'], stdout=subprocess.PIPE, text=True)

for line in process.stdout:
    print("Received:", line.strip())
    

Received: PING google.com (142.250.74.206): 56 data bytes
Received: 64 bytes from 142.250.74.206: icmp_seq=0 ttl=117 time=10.618 ms
Received: 64 bytes from 142.250.74.206: icmp_seq=1 ttl=117 time=11.203 ms
    

Here, stdout=subprocess.PIPE redirects the command's output to a pipe. Our Python script can then read from this pipe. This is a key technique for building interactive tools.

Common Pitfalls and Best Practices

Always use a list of arguments for the command. This prevents security issues and ensures arguments are passed correctly. Avoid using shell=True unless absolutely necessary.

Remember to handle encoding. Use text=True or decode bytes objects. Set a timeout with the timeout parameter to prevent hanging scripts.

For related tasks like reading files, you might use standard Python file handling. For managing multiple processes, look into Python's threading or multiprocessing modules.

Conclusion

Capturing output with Python's subprocess module is straightforward. Use subprocess.run() with capture_output=True for most tasks. Handle stdout and stderr separately for robust scripts.

For advanced streaming, subprocess.Popen is the tool. Follow best practices for security and reliability. This skill is fundamental for automating system tasks and integrating external tools into your Python workflows.