如何用 Python 调用外部命令

问题

 

也许大家在日常工作中遇到过要用 Python 脚本执行外部命令的情况,并且你还不知道怎么调用。Stack Overflow 热帖:如何用 Python 调用外部命令

 

没关系,早在 12 年前就有程序员在 Stack Overflow 上求助提问啦。

 

Stack Overflow 热帖:如何用 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.system 和 subprocess 那个解决方法更好一点呢?这里做简单讨论,虽然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() #输出ls -l 的结果

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、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)return_codeCompletedProcess(args='echo Hello World', returncode=0) #CompletedProcess对象type(return_code)

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 /”,是不是头皮发麻!Stack Overflow 热帖:如何用 Python 调用外部命令 所以谨慎再谨慎!!尽量不做交互式输入,而是在程序中,将要执行的命令,写“死”在字符串中,做为常量传递。

拓展思路

 

下面还整理了一些其它的方法,有兴趣的同学可再深入研究。

sh

sh程序是subprocess的接口,让你像调用函数一样的调用想执行的程序。如果要多次运行一个命令,这很有用。

sh.ls("-l") ls_cmd = sh.Command("ls")

plumbum

plumbum功能和sh类似。

ls_cmd = plumbum.local("ls -l") ls_cmd()

fabric

fabric 是py2.5和2.7的库。可以让你执行本地或远程shell命令。

fabric.operations.local('ls -l')fabric.operations.local('ls -l', capture = True)

envoy

envoy 以“subprocess for humans”闻名,它是对subprocess模块的封装,简单易用

r = envoy.run("ls -l"r.std_out

参考链接:

https://stackoverflow.com/questions/89228/how-to-call-an-external-command

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注