杰瑞科技汇

Python subprocess如何高效执行命令?

Of course! The term you're likely looking for is subprocess. It's a powerful and essential module in Python for running external commands and interacting with other programs directly from your script.

Python subprocess如何高效执行命令?-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering the basics, best practices, and common use cases.

What is the subprocess Module?

The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. In simple terms, it lets your Python script run command-line commands (like ls, git status, pip install, or any custom shell script) and capture their output.

It's the modern, recommended replacement for older modules like os.system, os.spawn, and the popen2 family.


Why Use subprocess?

  • Automate Tasks: Run repetitive command-line tasks automatically.
  • Integrate with Command-Line Tools: Use powerful tools like ffmpeg, curl, git, or aws from your Python application.
  • System Administration: Write scripts to manage servers, deploy applications, or perform system checks.
  • Data Processing: Pipe data between your Python script and other command-line utilities that excel at text processing (e.g., grep, awk, sed).

The Core Functions: A Quick Start

The subprocess module provides several functions. For most cases, you'll start with subprocess.run().

Python subprocess如何高效执行命令?-图2
(图片来源网络,侵删)

subprocess.run() (Recommended - The Modern Way)

This is the most flexible and recommended function. It runs a command, waits for it to complete, and then returns a CompletedProcess object.

Syntax: subprocess.run(args, *, ...) where args is a list of strings.

Key Parameters:

  • args: The command and its arguments as a list of strings. (e.g., ['ls', '-l', '/tmp']).
  • capture_output: If True, capture stdout and stderr. The output will be stored in the returned object.
  • text: If True, decode stdout and stderr as text using the default encoding. If False, they will be bytes. (Use with capture_output=True).
  • check: If True, raise a CalledProcessError if the process returns a non-zero exit code (indicating an error).
  • shell: If True, execute the command through the system's shell (e.g., /bin/sh on Linux). This can be a security risk if the command comes from untrusted input.

Common Use Cases with Examples

Let's explore the most common scenarios.

Case 1: Running a Command and Ignoring its Output

You just want to execute a command and don't care about what it prints.

import subprocess
# The command is a list: ['program', 'argument1', 'argument2']
command = ['echo', 'Hello from Python!']
# We use run() and don't capture output
result = subprocess.run(command)
print(f"Command '{' '.join(command)}' executed.")
print(f"Return code: {result.returncode}") # 0 means success

Output:

Hello from Python!
Command 'echo Hello from Python!' executed.
Return code: 0

Case 2: Capturing the Output as Text

This is extremely common. You run a command and need its output in a Python string.

import subprocess
command = ['ls', '-l']
# Run the command, capture output, and decode as text
result = subprocess.run(command, capture_output=True, text=True, check=True)
# The output is in the stdout attribute
print("--- Command Output ---")
print(result.stdout)
print("\n--- Return Code ---")
print(result.returncode)

Output (will vary based on your directory):

--- Command Output ---
total 16
drwxr-xr-x  3 user user 4096 Oct 26 10:30 .
drwxr-xr-x 15 user user 4096 Oct 26 10:29 ..
-rw-r--r--  1 user user  123 Oct 26 10:30 my_file.txt
--- Return Code ---
0

Case 3: Handling Errors

What if the command fails? The check=True parameter is your best friend.

import subprocess
# This command will fail because 'non_existent_command' doesn't exist
command = ['non_existent_command', '--some-flag']
try:
    # check=True will raise an exception if the command fails
    subprocess.run(command, check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e:
    print(f"Command failed with return code {e.returncode}")
    print(f"Error output (stderr): {e.stderr}")

Output:

Command failed with return code 127
Error output (stderr): /bin/sh: non_existent_command: command not found

Case 4: Passing Input to a Command

Sometimes you need to provide input to a command that reads from stdin.

import subprocess
# The 'sort' command reads from stdin and sorts the lines
command = ['sort']
# The input to be passed to the command
input_text = "banana\napple\ncherry\n"
# We use input= to provide the data
result = subprocess.run(
    command,
    input=input_text,
    capture_output=True,
    text=True
)
print("Sorted output:")
print(result.stdout)

Output:

Sorted output:
apple
banana
cherry

Case 5: Using the Shell (Use with Caution!)

Sometimes you need shell features like pipes (), globbing (), or environment variables ($VAR). For this, you can set shell=True.

WARNING: Using shell=True with untrusted input is a major security vulnerability (shell injection). Avoid it if possible.

import subprocess
# A command that uses a pipe, which requires the shell
command_string = "ls -l | grep py" # This is a string, not a list
print(f"Running command via shell: '{command_string}'")
# We pass the command as a single string and set shell=True
result = subprocess.run(command_string, shell=True, capture_output=True, text=True)
print("\n--- Output ---")
print(result.stdout)

Output (assuming you have Python files in the directory):

Running command via shell: 'ls -l | grep py'
--- Output
-rw-r--r-- 1 user user 1234 Oct 26 10:30 my_script.py
-rw-r--r-- 1 user user 5678 Oct 26 10:31 utils.py

Key Differences Between run(), call(), check_output(), and Popen()

Function Description Best For
subprocess.run() (Recommended) Runs command, waits, returns CompletedProcess object. Almost everything. It's the most flexible and modern choice.
subprocess.call() Runs command, waits, returns the returncode. Simple cases where you only need the exit code and don't care about output.
subprocess.check_output() Runs command, waits, returns stdout. Raises error on non-zero exit. When you only need the standard output and want an error on failure.
subprocess.Popen() Spawns a process without waiting for it. Advanced use cases: running commands concurrently, interacting with a process's stdin/stdout/stderr in real-time (e.g., ssh, ftp).

Security Warning: shell=True

Never use shell=True with input you don't fully control.

Consider this dangerous code:

# DANGEROUS! DO NOT DO THIS!
user_input = "malicious; rm -rf /"
subprocess.run(f"echo {user_input}", shell=True)

The shell would interpret this as two commands:

  1. echo malicious
  2. rm -rf /

The second command would recursively delete your entire root filesystem! Always prefer passing arguments as a list (args=['ls', '-l', user_path]) over using shell=True with a string.

分享:
扫描分享到社交APP
上一篇
下一篇