subprocess.run()是最安全的调用方式,它启动新进程、隔离环境、可捕获输出与设超时,避免污染当前解释器;exec()仅适用于可信小片段,因无进程隔离而易致变量冲突与导入污染;popen适合实时交互场景但需手动管理资源;路径与解释器应使用sys.executable和绝对路径确保跨平台稳定。

subprocess.run() 是最安全的调用方式
直接执行另一个 Python 脚本,subprocess.run() 是默认推荐方案。它开新进程、隔离环境、能捕获输出、可设超时,不会污染当前解释器状态。
常见错误现象:exec() 或 execfile()(Python 2)直接执行脚本代码,导致变量名冲突、sys.argv 错乱、异常堆栈不清晰;用 os.system() 则无法可靠获取返回值或标准输出。
- 使用场景:需要独立运行、传参、等结果、处理错误码
- 参数差异:
subprocess.run(["python", "other.py", "arg1", "arg2"])比shell=True更安全,避免 shell 注入;Windows 下注意可执行文件名是python.exe还是python - 性能影响:启动新进程有开销,但换来的是稳定性 —— 不值得为省几毫秒牺牲隔离性
- 示例:
result = subprocess.run(["python", "helper.py", "--verbose"], capture_output=True, text=True, timeout=30);检查result.returncode和result.stdout
exec() 只适用于极简、可信、无副作用的代码片段
exec() 不启动新进程,只是把字符串或文件内容当 Python 代码在当前作用域执行。它快,但也危险 —— 全局变量被覆盖、导入污染、异常位置难追踪。
常见错误现象:执行完 other.py 后发现自己的 config 变量被重写了;import numpy 在子脚本里执行后,主脚本突然能用 np 了,但实际没 import;调试时断点跳进一堆不可见的 exec 内容里。
- 使用场景:加载本地配置文件(如
exec(open("config.py").read())),或动态生成少量逻辑(如模板化小函数) - 参数差异:必须传入
globals()和locals()显式控制作用域,否则默认写入当前全局空间;建议用空字典隔离:exec(code, {"__builtins__": {}}, {}) - 兼容性影响:Python 3.12+ 对
exec()的限制更严,某些动态行为可能报RuntimeError - 示例:
with open("tiny_utils.py") as f: exec(f.read(), {}, local_ns := {}),之后用local_ns["helper_func"]
subprocess.Popen() 适合需要实时交互或长时运行的脚本
当你要边执行边读日志、发信号、或让子脚本后台跑着,subprocess.Popen() 比 run() 更灵活。但它不自动等待,容易忘记 .wait() 或 .communicate(),导致僵尸进程。
华为云 Python SDK 查询工具。自动发现已安装 SDK 的服务包、Client类、API 方法、入参详情、类信息(__init__ 参数、属性、类型、描述),支持关键字搜索,快速定位目标 API 使用方法。
常见错误现象:脚本看似执行完,但后台 python other.py 还在跑;用 .stdout.readline() 却卡住 —— 因为子进程 stdout 默认行缓冲,没 flush;stderr 没重定向,错误信息直接打到终端,难以捕获。
- 使用场景:监控子脚本输出、实现管道(如
other.py | grep "done")、子进程需响应 SIGTERM - 参数差异:务必设
stdout=subprocess.PIPE和stderr=subprocess.STDOUT才能读取;加universal_newlines=True(或text=True)避免 bytes/str 混用 - 性能影响:比
run()多一层对象管理,但换来流式处理能力;频繁调用要注意资源释放 - 示例:
proc = subprocess.Popen(["python", "long_runner.py"], stdout=subprocess.PIPE, text=True); for line in proc.stdout: print(line.strip())
路径和 Python 解释器选择是隐形坑最多的地方
脚本能运行,不代表它在任何地方都能运行。相对路径、sys.path、虚拟环境、Python 版本错位,这些不报错,但行为诡异。
常见错误现象:subprocess.run(["python", "utils.py"]) 在 IDE 里成功,命令行失败 —— 因为 IDE 自动激活了 venv,而终端没;other.py 里用 from lib import x,但被调用时 lib 不在子进程的 sys.path;Windows 上写 python3,Linux 报 command not found。
- 使用场景:跨平台部署、CI/CD 环境、打包成可执行文件
- 参数差异:用
shutil.which("python")或sys.executable替代硬编码"python";用Path(__file__).parent / "other.py"构造绝对路径 - 兼容性影响:Windows 的
python.exe和 macOS/Linux 的python3行为略有不同,统一用sys.executable最稳 - 示例:
subprocess.run([sys.executable, Path(__file__).parent / "worker.py"])
真正麻烦的不是选哪个方法,而是子脚本自己有没有隐式依赖当前工作目录、环境变量、或某个特定版本的包 —— 这些不会在 subprocess 报错里体现,得靠日志和复现环境一点点对齐。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










