- 使用
os.system():简单直接,适合执行简单的命令。 - 使用
subprocess模块:功能强大、灵活、安全,是现代 Python 推荐的最佳实践。
下面我将详细介绍这两种方法,并提供完整的代码示例。

场景设定
假设我们有两个文件:
main_script.py(调用者,负责执行另一个脚本)called_script.py(被调用者,接收参数并执行)
我们的目标是让 main_script.py 调用 called_script.py,并传递一些参数。
被调用脚本: called_script.py
这个脚本需要能够接收和处理命令行参数,Python 内置的 sys 模块可以轻松实现这一点。
# called_script.py
import sys
import time
print(f"脚本 {__file__} 开始运行...")
# sys.argv 是一个列表,包含了所有的命令行参数
# sys.argv[0] 是脚本本身的名称
# sys.argv[1] 是第一个参数,以此类推
if len(sys.argv) > 1:
print(f"接收到的参数数量: {len(sys.argv) - 1}")
for i, arg in enumerate(sys.argv[1:], start=1):
print(f" 参数 {i}: {arg}")
else:
print("没有接收到任何参数。")
# 演示如何根据参数执行不同操作
if len(sys.argv) > 1 and sys.argv[1] == "--hello":
print("你好,世界!")
elif len(sys.argv) > 1 and sys.argv[1].startswith("--count="):
# 示例: --count=5
try:
count_str = sys.argv[1].split('=')[1]
count = int(count_str)
for i in range(count):
print(f"计数: {i + 1}")
time.sleep(0.5)
except (IndexError, ValueError):
print("错误: 请使用正确的格式,--count=5")
else:
print("可用参数: --hello, --count=<数字>")
print(f"脚本 {__file__} 运行结束。")
使用 os.system() (简单但有限)
os.system() 函数会将字符串作为命令传递给系统的 shell (如 Linux 下的 Bash 或 Windows 下的 CMD) 来执行。

优点:
- 语法非常简单,一行代码就能搞定。
缺点:
- 不安全:如果参数来自用户输入,容易导致命令注入漏洞。
- 功能有限:很难获取被调用脚本的输出或返回码。
- 平台依赖:不同操作系统的命令语法可能不同。
调用脚本: main_os_system.py
# main_os_system.py
import os
print("--- 使用 os.system() 调用脚本 ---")
# 定义要执行的命令
# 注意:参数之间用空格隔开
command = "python called_script.py --hello --count=3"
print(f"准备执行命令: {command}")
# 执行命令
return_code = os.system(command)
print(f"\n命令执行完毕,返回码: {return_code}")
如何运行:
python main_os_system.py
输出:
--- 使用 os.system() 调用脚本 ---
准备执行命令: python called_script.py --hello --count=3
脚本 called_script.py 开始运行...
接收到的参数数量: 2
参数 1: --hello
参数 2: --count=3
你好,世界!
可用参数: --hello, --count=<数字>
计数: 1
计数: 2
计数: 3
脚本 called_script.py 运行结束。
命令执行完毕,返回码: 0
使用 subprocess 模块 (推荐)
subprocess 模块是 Python 官方推荐用于创建和管理子进程的工具,它提供了更强大、更灵活、更安全的方式来执行外部命令。
核心函数:
subprocess.run(): Python 3.5+ 引入的推荐函数,功能全面,易于使用。subprocess.Popen(): 更底层、更强大的类,适用于复杂的交互场景。
我们重点介绍 subprocess.run()。
调用脚本: main_subprocess.py
# main_subprocess.py
import subprocess
import sys
print("--- 使用 subprocess.run() 调用脚本 ---")
# 1. 最简单的用法:直接传递参数列表
# ['python', 'called_script.py', '--hello', '--count', '3']
# 这种方式可以避免 shell 注入,更安全。
try:
print("\n--- 示例1: 基本调用 ---")
result = subprocess.run(
['python', 'called_script.py', '--hello', '--count', '3'],
check=True, # 如果返回码不为0,则抛出 CalledProcessError 异常
capture_output=True, # 捕获标准输出和标准错误
text=True, # 将输出解码为文本 (Python 3.7+)
encoding='utf-8' # 指定编码
)
print("子进程执行成功!")
print(f"返回码: {result.returncode}")
print("--- 标准输出 ---")
print(result.stdout)
print("--- 标准错误 ---")
if result.stderr:
print(result.stderr)
else:
print("(无标准错误)")
except subprocess.CalledProcessError as e:
print(f"子进程执行失败,返回码: {e.returncode}")
print(f"错误输出: {e.stderr}")
# 2. 带有超时和用户输入的调用
print("\n--- 示例2: 带超时和输入的调用 ---")
try:
# 我们修改 called_script.py 让它接收用户输入
# 这里我们模拟输入 "yes"
process = subprocess.run(
['python', 'called_script.py'],
input="yes\n", # 发送输入到子进程的标准输入
capture_output=True,
text=True,
timeout=5 # 设置超时时间(秒)
)
print("带输入的子进程执行成功!")
print(f"返回码: {process.returncode}")
print("--- 标准输出 ---")
print(process.stdout)
except subprocess.TimeoutExpired:
print("错误: 子进程执行超时!")
except subprocess.CalledProcessError as e:
print(f"子进程执行失败,返回码: {e.returncode}")
如何运行:

python main_subprocess.py
输出:
--- 使用 subprocess.run() 调用脚本 ---
--- 示例1: 基本调用 ---
子进程执行成功!
返回码: 0
--- 标准输出 ---
脚本 called_script.py 开始运行...
接收到的参数数量: 4
参数 1: --hello
参数 2: --count
参数 3: 3
你好,世界!
可用参数: --hello, --count=<数字>
计数: 1
计数: 2
计数: 3
脚本 called_script.py 运行结束。
--- 标准错误 ---
(无标准错误)
--- 示例2: 带超时和输入的调用 ---
脚本 called_script.py 开始运行...
没有接收到任何参数。
可用参数: --hello, --count=<数字>
脚本 called_script.py 运行结束。
带输入的子进程执行成功!
返回码: 0
--- 标准输出 ---
脚本 called_script.py 开始运行...
没有接收到任何参数。
可用参数: --hello, --count=<数字>
脚本 called_script.py 运行结束。
(注意:示例2的输出中,called_script.py 没有设计使用输入,所以输入 "yes" 没有被处理,但程序正常执行完毕,这只是为了演示 input 参数的用法。)
总结与对比
| 特性 | os.system() |
subprocess 模块 (推荐) |
|---|---|---|
| 易用性 | 非常简单,易于上手 | 稍微复杂,但 run() 函数已大大简化 |
| 安全性 | 低,直接拼接字符串,有命令注入风险。 | 高,推荐使用参数列表形式,避免 shell 解析。 |
| 功能 | 有限,难以获取输出、返回码或与子进程交互。 | 强大,可轻松捕获输出/错误、获取返回码、设置超时、管道输入输出等。 |
| 平台兼容性 | 依赖底层 shell,可能存在跨平台问题。 | Python 内置,跨平台行为一致,更可靠。 |
| 推荐度 | 仅用于快速、简单的、无参数或固定参数的脚本调用。 | 强烈推荐,适用于所有场景,特别是需要处理参数、获取结果或进行复杂交互时。 |
最佳实践
- 始终优先使用
subprocess模块。 - 使用
subprocess.run(),除非你需要Popen提供的更高级功能(如实时交互)。 - 将命令和参数作为列表传递,
['python', 'script.py', '--arg', 'value'],而不是通过字符串拼接,这是防止 shell 注入最安全的方式。 - 使用
check=True来检查子进程是否成功执行,如果失败会抛出异常,方便你进行错误处理。 - 使用
capture_output=True和text=True来方便地获取和处理子进程的文本输出。
