How do I execute a program or call a system command in Python?

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

MethodUse CaseSecurity
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

  1. Avoid shell=True unless necessary (exposes shell injection risks).
  2. 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!
  1. Prefer subprocess over os.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.

Leave a Reply

Your email address will not be published. Required fields are marked *