如何用Python调用外部命令

解决方法

方法1:我们可以使用subprocess,比如要执行 ls -l 命令

import subprocess
subprocess.run("ls", "-l")

Python3.5 之前的版本,需要使用 call

import subprocess
subprocess.call(["ls", "-l"])

方法2:

import os
os.system("ls -l")
os.popen("ls -l").read()
方法讨论:

问题解决了,那么os.systemsubprocess哪个解决方法更好呢?这里做简单讨论,虽然os.system 和 subprocess 都能完成外部命令功能,但是subprocess比system更加灵活(subprocess 我们可以得到 stdout,stderr 以及更好的错误处理等等)。并且官方文档也是更建议subprocess模块。

总觉:

1、os.system("some_command with args"):将命令和参数传给系统shell,这个方法可以一次执行多条命令,并且可以建立管道重定向。

os.system("some_command < input_file | another_command > output_file ")

尽管这种方式很简便,但是你不得不手工处理一些特殊字符例如空格等。
2、stream = os.popen("some_command with args"):实现功能和os.system是一样的,但是os.popen会返回一个类文件对象,让你看到命令的执行结果。

stream = os.popen("ls -l")
stream.read()

3、subprocess 的 Popen 类,建议尽量使用它来替代os.popen,但是使用的时参数会相对复杂

print(subprocess.Popen("echo Hello Worldd", shell=True, stdout=subprocess.PIPE).stdout.read())

而不建议使用

print(os.popen("echo Hello World")).read()

4、subprocess 模块中 call 函数,功能和Popen类相似,并且使用相同的参数,但是它仅仅在命令执行完毕后,返回一个代码

return_code = subprocess.call("echo Hello World", shell=True)
0 # 执行成功

5、如果使用时Python3.5及以上版本,可以使用subprocess.run函数,它跟上面介绍的函数基本一样,但是更加灵活,会在命令执行结束后返回一个CompletedProcess对象。

return_code = subprocess.run("echo Hello World", shell=True)
print return_code
>>> CompletedProcess(args='echo Hello World', return_code=0)

6、虽然os模块包括fork/exec/spawn等函数,但是并不建议直接使用它们,使用不当会导致意外的结果。
因此如果有需要执行的外部命令的需要,建议使用 subprocess,而非os模块。

最后,特别要注意如果你要执行的命令是以字符串的形式作为参数,那么必须小心谨慎,否则会造成严重的后果!
例如:

print(subprocess.Popen("echo %s" % user_input, stdout=PIPE).stdout.read())

看到这段代码能想到什么可怕的事情吗?如果有人给 user_input 传递的是“my mama didnt love me && rm -rf /”,是不是头皮发麻!所以谨慎再谨慎!尽量不做交互是输入,而是在程序中将要执行的命令,写‘死’在字符串中,作为常量传递。

你可能感兴趣的:(如何用Python调用外部命令)