如何在 Python 中调用外部命令,就像我在 shell 或命令提示符下键入它一样?
使用标准库中的 subprocess 模块:
import subprocess
# 对于简单命令
subprocess.run(["ls", "-l"])
# 对于有很多参数的复杂命令,使用 string + `shell=True`:
cmd_str = "ls -l /tmp | awk '{print $3,$9}' | grep root"
subprocess.run(cmd_str, shell=True)
subprocess.run 对比 os.system 的优势在于它更灵活(你可以获得 stdout、stderr、“真实”状态代码、更好的错误处理等)。
甚至 os.system 的文档也建议使用:subprocess
subprocess
模块为生成新进程和检索其结果提供了更强大的功能;使用该模块比使用此函数更可取。有关一些有用的诀窍,请参阅 subprocess
文档中的subprocess-replacements 。
在Python 3.4及更早版本上,使用 subprocess.call 而不是 .run:
subprocess.call(["ls", "-l"])
部分其他方式总结
1. os.system 将命令和参数传递给系统的 shell。这很好,因为你实际上可以以这种方式一次运行多个命令,并设置管道和输入/输出重定向。例如:
os.system("some_command < input_file | another_command > output_file")
但是,虽然这很方便,但你必须手动处理 shell 字符(如空格等)的转义。另一方面,这也允许你运行简单的 shell 命令而不是实际外部程序的命令。
2. os.popen 将执行与 OS 相同的操作,只是它为你提供了一个类似文件的对象,你可以使用该对象访问该过程的标准输入/输出。popen 还有其他 3 种变体,它们处理 I/O 的方式略有不同。如果将所有内容作为字符串传递,则命令将传递给 shell; 如果你将它们作为列表传递,则无需担心转义任何内容。例如:
print(os.popen("ls -l").read())
3. subprocess.Popen 这是作为 os.popen 的替代品,但它的缺点是由于过于全面而略显复杂。例如,你可以说:
print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()
而不是
print os.popen("echo Hello World").read()
但是将所有选项放在一个统一的类中而不是 4 个不同的 popen 函数中是很好的。请参阅popen-constructor。
参考:stackoverflow question 89228
PS:
本文首发于公众号: 程序熵, 更多相关文章请添加关注code-shang