To execute a program or call a system command in Python, you can use the subprocess
module (recommended for modern code) or the older os.system()
function. Below are common methods with examples:
1. Using subprocess.run()
(Python 3.5+)
The modern and flexible way to execute commands, with full control over inputs, outputs, and errors.
Basic Command Execution
import subprocess
# Run a command (returns a CompletedProcess object)
result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
# Check output and errors
print("Exit code:", result.returncode)
print("Output:", result.stdout)
print("Errors:", result.stderr)
Handle Errors
try:
subprocess.run(["invalid_command"], check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e:
print(f"Command failed: {e.stderr}")
Run with Shell (Use Sparingly)
# Avoid unless necessary (security risk with untrusted input)
subprocess.run("echo Hello, $USER", shell=True, text=True)
2. Using subprocess.check_output()
(Python 3.5+)
Capture the command’s output directly:
output = subprocess.check_output(["date"], text=True)
print("Today is:", output.strip()) # Output: "Today is: Mon Oct 2 12:00:00 PDT 2023"
3. Using os.system()
(Legacy Method)
Simple but limited (returns exit code, not output):
import os
exit_code = os.system("ls -l")
print("Exit code:", exit_code) # 0 for success, non-zero for failure
4. Advanced: subprocess.Popen()
For low-level control (e.g., pipes, asynchronous execution):
# Run a command and read output line-by-line
process = subprocess.Popen(["ping", "google.com"], stdout=subprocess.PIPE, text=True)
while True:
line = process.stdout.readline()
if not line:
break
print(line.strip())
Key Considerations
Method | Use Case | Security |
---|---|---|
subprocess.run() | Modern, flexible execution. | Safe with shell=False . |
subprocess.check_output() | Capture output directly. | Avoid shell=True . |
os.system() | Legacy scripts (limited use). | Risky with untrusted input. |
subprocess.Popen() | Advanced use (e.g., pipes, async). | Handle with care. |
Best Practices
- Avoid
shell=True
unless necessary (exposes shell injection risks). - Use lists for commands instead of strings to prevent injection:
# Safe (no shell=True)
subprocess.run(["ls", "-l"])
# Risky (shell=True with user input)
user_input = "malicious_command; rm -rf /"
subprocess.run(user_input, shell=True) # Dangerous!
- Prefer
subprocess
overos.system
for better control and security.
Example: Run a Command and Capture Output
import subprocess
def run_command(command):
result = subprocess.run(command, capture_output=True, text=True)
if result.returncode == 0:
return result.stdout.strip()
else:
raise Exception(f"Command failed: {result.stderr}")
# Usage
try:
output = run_command(["git", "--version"])
print("Git version:", output) # e.g., "git version 2.34.1"
except Exception as e:
print(e)
By using subprocess
, you gain precise control over command execution while maintaining security and cross-platform compatibility.