commands 模块在 Python 3 中已经被移除了。
如果你正在使用 Python 3,你无法也不需要安装 commands 模块,直接安装它会失败,因为该模块本身已经不存在了。
为什么 commands 模块被移除了?
commands 模块(主要存在于 Python 2 中)的设计存在一些安全隐患和功能上的缺陷,最核心的问题是它无法安全地处理包含特殊字符(如空格、引号、分号等)的命令或文件名,它返回的输出和状态码是分开的,使用起来不够方便。
为了解决这些问题,Python 社区引入了更强大、更安全的替代品,也就是我们接下来要重点介绍的 subprocess 模块。
正确的解决方案:使用 subprocess 模块
subprocess 是 Python 官方推荐用于调用外部命令的模块,它功能强大、灵活且安全,无论你使用的是 Python 2 还是 Python 3,都应该学习和使用 subprocess。
subprocess 模块是 Python 的标准库之一,无需安装,直接导入即可使用。
subprocess 提供了多种运行命令的方式,以满足不同的需求,以下是几个最常用的函数:
subprocess.run() (推荐,Python 3.5+)
这是最现代、最通用的方式,它会执行命令,等待其完成,然后返回一个 CompletedProcess 对象。
示例:执行一个简单的命令,并获取其输出
import subprocess
# 执行 'ls -l' 命令 (在 Linux/macOS 上)
# 在 Windows 上,可以使用 'dir'
try:
# capture_output=True 会捕获标准输出和标准错误
# text=True 会将输出解码为文本(而不是字节)
# check=True 会在命令返回非零退出码(即失败)时抛出 CalledProcessError 异常
result = subprocess.run(['ls', '-l'], capture_output=True, text=True, check=True)
print("命令执行成功!")
print("返回码:", result.returncode)
print("标准输出:\n", result.stdout)
# print("标准错误:", result.stderr) # 如果有错误信息会在这里
except FileNotFoundError:
print("错误:命令 'ls' 未找到,请确保在正确的操作系统上运行或使用正确的命令。")
except subprocess.CalledProcessError as e:
print(f"命令执行失败,返回码: {e.returncode}")
print(f"标准错误: {e.stderr}")
subprocess.Popen() (最灵活,适用于所有版本)
Popen 是 subprocess 的核心类,它提供了最底层的控制,当你需要与子进程进行更复杂的交互(比如实时发送输入或读取输出)时,Popen 是不二之选。
示例:启动一个进程并与其交互
import subprocess
# 启动一个进程
process = subprocess.Popen(['python3', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
# 等待进程结束并获取输出
stdout, stderr = process.communicate()
print("进程的返回码:", process.returncode)
print("标准输出:", stdout)
print("标准错误:", stderr)
subprocess.check_output() (简单获取输出)
如果你只想执行一个命令并获取其标准输出,并且不关心错误输出(或者希望命令失败时抛出异常),这个函数非常方便。
示例:获取 Python 版本
import subprocess
try:
# 执行命令并获取输出,如果命令失败会抛出 CalledProcessError
output = subprocess.check_output(['python3', '--version'], text=True)
print(output.strip()) # .strip() 用于移除末尾的换行符
except subprocess.CalledProcessError as e:
print(f"命令执行失败: {e}")
except FileNotFoundError:
print("错误:未找到 'python3' 命令。")
总结与对比
| 特性 | commands (Python 2) |
subprocess (Python 2 & 3) |
|---|---|---|
| 可用性 | 仅 Python 2 | 所有 Python 版本 |
| 安全性 | 不安全,易受 shell 注入攻击 | 安全,默认不调用 shell |
| 功能 | 功能简单,功能有限 | 功能强大,灵活控制输入/输出/环境等 |
| 返回值 | 输出和状态码分离 | 返回包含所有信息的对象 |
| 推荐度 | 已废弃,不要使用 | 官方推荐,标准做法 |
最终建议
-
如果你正在使用 Python 2:
- 尽快升级到 Python 3。
- 如果无法升级,请将你的
commands模块代码迁移到subprocess模块,这是未来的方向,也更安全。
-
如果你正在使用 Python 3:
- 忘记
commands模块的存在。 - 直接学习和使用
subprocess模块。 - 对于大多数常见任务,从
subprocess.run()开始是一个很好的选择。 - 如果需要更复杂的交互(如管道、实时通信),再使用
subprocess.Popen()。
- 忘记
你不需要安装 commands 模块,请直接使用 Python 内置的 subprocess 模块来执行系统命令。
