Explain Codes LogoExplain Codes Logo

Store output of subprocess.Popen call in a string

python
subprocess
process-management
error-handling
Nikita BarsukovbyNikita Barsukov·Jan 17, 2025
TLDR

Here's the Pythonic way to capture the output of a command with subprocess.Popen:

import subprocess process = subprocess.Popen(["cmd", "arg"], stdout=subprocess.PIPE) # And as Simply Red would say: "If you don't know 'decode' by now..." output = process.communicate()[0].decode()

Enhanced output capture: exceptions and error handling

Dealing with errors as they come

Receiving errors from your processes should be as easy as ordering a drink at Starbucks:

try: # Let's go process some coffee... process = subprocess.Popen(["brew", "coffee"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = process.communicate() # If the coffee (command) hasn't brewed (executed) well... if process.returncode != 0: print(f"Spilled the coffee (error): {error.decode()} 😞") else: print(f"Coffee is ready (output): {output.decode()} ☕️") except Exception as e: print(f"Couldn't brew the coffee (command failed): {str(e)}")

Tips & tricks: command arguments, security & more

Crafting command arguments

Passing the command and its arguments as a list instead of a string helps to avoid shell injection attacks:

command = ["brew", "coffee"] process = subprocess.Popen(command, stdout=subprocess.PIPE) # Be sure to ".decode()" your coffee! output = process.communicate()[0].decode("utf-8")

Working with command execution

Ensuring a successful command run

Here, we're handling timeouts and interactive commands, which are cooler than cucumbers in a bowl of hot sauce:

process = subprocess.Popen([r"/path/to/cool/command"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) try: output, _ = process.communicate(b'data to process here (input)\n', timeout=9) except subprocess.TimeoutExpired: process.kill() output, _ = process.communicate() # Plan B...