subprocess.run 是推荐的方法as of Python 3.5,如果您的代码不需要保持与早期Python版本的兼容性 . 尽管如此,'s more consistent and offers similar ease-of-use as Envoy. (Piping isn' t直截了当 . 见this question for how . )
subprocess.run(["ls", "-l"]) # Run command
subprocess.run(["ls", "-l"], stdout=subprocess.PIPE) # This will run the command and return any output
subprocess.run(shlex.split("ls -l")) # You can also use the shlex library to split the command
pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo user@example.com:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')
import subprocess
p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
print line,
retval = p.wait()
30 回答
如果您需要调用的命令的输出,则可以使用subprocess.check_output(Python 2.7) .
另请注意shell参数 .
https://docs.python.org/2/library/subprocess.html
......或者是一个非常简单的命令:
请注意,这是危险的,因为未清除该命令 . 我把它留给你去谷歌搜索关于'os'和'sys'模块的相关文档 . 有许多函数(exec *和spawn *)可以执行类似的操作 .
没有结果的输出:
输出结果:
os.system
不允许您存储结果,因此如果您想将结果存储在某个列表或某些内容中,subprocess.call
可以正常工作 .这里有另一个不同之处,前面没有提到过 .
subprocess.Popen
将<command>作为子进程执行 . 在我的例子中,我需要执行需要与另一个程序进行通信的文件<a> <b> .我尝试了subprocess,执行成功了 . 但是<b>无法与<a>通信 . 当我从终端运行时,一切正常 .
还有一个:(注意:kwrite的行为与其他应用程序不同 . 如果您使用Firefox尝试以下操作,结果将不同 . )
如果您尝试
os.system("kwrite")
,程序流将冻结,直到用户关闭kwrite . 为了克服这一点,我尝试了os.system(konsole -e kwrite)
. 这个时间程序继续流动,但kwrite成为控制台的子进程 .任何人都运行kwrite不是一个子进程(即在系统监视器中它必须出现在树的最左边) .
你可以使用Popen,然后你可以检查程序的状态:
看看subprocess.Popen .
有关将子进程与调用进程分离的一些提示(在后台启动子进程) .
假设您想从CGI脚本启动一个长任务,即子进程应该比CGI脚本执行过程更长寿 .
子流程模块docs的经典示例是:
这里的想法是你不想在“调用子进程”行中等待,直到longtask.py完成 . 但目前尚不清楚在这个例子中“更多代码”这一行之后会发生什么 .
我的目标平台是freebsd,但是开发是在windows上进行的,所以我首先在windows上遇到了问题 .
在Windows(win xp)上,父进程将不会完成,直到longtask.py完成其工作 . 这不是你想要的CGI脚本 . 问题不是Python特有的,在PHP社区中问题是一样的 .
解决方案是将DETACHED_PROCESS Process Creation Flag传递给win API中的底层CreateProcess函数 . 如果你碰巧安装了pywin32,你可以从win32process模块导入标志,否则你应该自己定义:
/ * UPD 2015.10.27 @eryksun在下面的评论中指出,语义正确的标志是CREATE_NEW_CONSOLE(0x00000010)* /
在freebsd上我们还有另一个问题:父进程完成后,它也会完成子进程 . 这也不是你想要的CGI脚本 . 一些实验表明问题似乎在于共享sys.stdout . 工作解决方案如下:
我没有检查其他平台上的代码,也不知道freebsd上的行为原因 . 如果有人知道,请分享您的想法 . 谷歌搜索在Python中启动后台进程尚未解决任何问题 .
它可以很简单:
如果要返回命令的结果,可以使用os.popen . 但是,从版本2.6开始,这已经被弃用了subprocess module,其他答案已经很好地解决了 .
我非常喜欢shell_command,因为它简单 . 它 Build 在子进程模块之上 .
以下是文档中的示例:
简单,使用
subprocess.run
,它返回一个CompletedProcess
对象:为什么?
从Python 3.5开始,文档建议subprocess.run:
这是一个最简单的使用示例 - 它确实如此完全如我所说:
run
等待命令成功完成,然后返回CompletedProcess
对象 . 它可能会提升TimeoutExpired
(如果你给它一个timeout=
参数)或CalledProcessError
(如果它失败并且你传递check=True
) .正如您可能从上面的示例中推断的那样,默认情况下,stdout和stderr都会通过管道输出到您自己的stdout和stderr .
我们可以检查返回的对象并查看给出的命令和返回码:
捕获输出
如果要捕获输出,可以将
subprocess.PIPE
传递给相应的stderr
或stdout
:(我觉得有趣且有点违反直觉,版本信息被放到stderr而不是stdout . )
传递命令列表
人们可以轻松地从手动提供命令字符串(如问题建议)到提供以编程方式构建的字符串 . Don't build strings programmatically. 这是一个潜在的安全问题 . 它's better to assume you don'吨信任输入 .
注意,只有
args
应该在位置上传递 .完整签名
这是源中的实际签名,如
help(run)
所示:popenargs
和kwargs
被赋予Popen
构造函数 .input
可以是一串字节(或unicode,如果指定编码或universal_newlines=True
),它将被传送到子进程的stdin .该文档描述了
timeout=
和check=True
比我更好:这个
check=True
的例子比我想出的更好:扩展签名
这是一个扩展的签名,如文档中所示:
请注意,这表示只应按位置传递args列表 . 因此将剩余的参数作为关键字参数传递 .
Popen
当使用
Popen
时?我很难根据论据单独找到用例 . 但是,直接使用Popen
可以访问其方法,包括poll
,'send_signal','terminate'和'wait' .这是the source中给出的
Popen
签名 . 我认为这是对信息的最精确封装(与help(Popen)
相对):但更多信息是the Popen documentation:
了解
Popen
上的其余文档将留给读者练习 .在Windows中,您可以通过调用
subprocess.Popen()
,subprocess.Popen().communicate()
和subprocess.Popen().wait()
来导入subprocess
模块并运行外部命令,如下所示:输出:
使用标准库
使用subprocess module(Python 3):
这是推荐的标准方式 . 但是,更复杂的任务(管道,输出,输入等)构造和写入可能很繁琐 .
关于Python版本的注意事项:如果您仍在使用Python 2,subprocess.call的工作方式类似 .
ProTip:shlex.split可以帮助你解析
run
,call
和其他subprocess
函数的命令,以防你't want (or you can' t!)以列表的形式提供它们:具有外部依赖关系
如果您不介意外部依赖项,请使用plumbum:
它是最好的
subprocess
包装器 . 它是跨平台的,即它适用于Windows和类Unix系统 . 按pip install plumbum
安装 .另一个受欢迎的图书馆是sh:
但是,
sh
放弃了Windows支持,所以它不像过去那样棒 . 按pip install sh
安装 .我倾向于将subprocess与shlex一起使用(以处理引用字符串的转义):
更新:
subprocess.run
是推荐的方法as of Python 3.5,如果您的代码不需要保持与早期Python版本的兼容性 . 尽管如此,'s more consistent and offers similar ease-of-use as Envoy. (Piping isn' t直截了当 . 见this question for how . )以下是the docs的一些例子 .
运行一个过程:
提高失败的运行:
捕获输出:
原始答案:
我建议尝试Envoy . 它是子进程的包装器,而后者又是aims to replace旧的模块和函数 . 特使是人类的子过程 .
the readme的用法示例:
管道周围的东西:
我建议使用子进程模块而不是os.system,因为它会为你进行shell转义,因此更加安全:http://docs.python.org/library/subprocess.html
以下是调用外部程序的方法及其优缺点的摘要:
os.system("some_command with args")
将命令和参数传递给系统的shell . 这很好,因为您实际上可以以这种方式一次运行多个命令并设置管道和输入/输出重定向 . 例如:但是,虽然这很方便,但您必须手动处理shell字符的转义,例如空格等 . 另一方面,这也允许您运行只是shell命令而不是外部程序的命令 . 见the documentation .
stream = os.popen("some_command with args")
将执行与_77120相同的操作,除了它为您提供了一个类似文件的对象,您可以使用该对象访问该进程的标准输入/输出 . 还有3种其他的popen变体,它们对i / o的处理方式略有不同 . 如果您将所有内容都作为字符串传递,那么您的命令将传递给shell;如果你将它们作为列表传递,那么你不必担心逃避任何事情 . 见the documentation .subprocess
模块的Popen
类 . 这是为了取代os.popen
,但由于其如此全面,因此具有稍微复杂的缺点 . 例如,你会说:代替:
但是在一个统一的类而不是4个不同的popen函数中拥有所有选项是很好的 . 见the documentation .
subprocess
模块中的call
函数 . 这基本上就像Popen
类一样,并且接受所有相同的参数,但它只是等待命令完成并为您提供返回代码 . 例如:见the documentation .
如果您使用的是Python 3.5或更高版本,则可以使用新的subprocess.run函数,该函数与上述函数非常相似,但更灵活,并在命令完成执行时返回CompletedProcess对象 .
os模块还具有C程序中的所有fork / exec / spawn函数,但我不建议直接使用它们 .
subprocess
模块可能应该是你使用的 .最后请注意,对于所有将shell执行的最终命令作为字符串传递的方法,您负责转义它 . There are serious security implications 如果您传递的字符串的任何部分无法完全信任 . 例如,如果用户正在输入字符串的某些/任何部分 . 如果您不确定,请仅将这些方法与常量一起使用 . 为了给您一些暗示,请考虑以下代码:
并想象用户输入“我的妈妈不爱我&& rm -rf /” .
使用:
os - This module provides a portable way of using operating system-dependent functionality.
对于更多
os
函数,here是文档 .检查“pexpect”Python库 .
它允许交互式控制外部程序/命令,甚至ssh,ftp,telnet等 . 您只需键入以下内容:
在Linux下,如果你想调用一个独立执行的外部命令(将在python脚本终止后继续运行),你可以使用一个简单的队列作为task spooler或at命令
任务假脱机程序的示例:
有关任务假脱机程序的注释(
ts
):ts -S <number-of-slots>
ts
不需要管理员权限 . 您可以使用简单的make
从源代码下载并编译它,将其添加到您的路径中,您就完成了 .os.system
没关系,但有点过时了 . 它也不是很安全 . 相反,请尝试subprocess
.subprocess
不直接调用sh,因此比os.system
更安全 .获取更多信息here .
我总是使用
fabric
这样的东西:但这似乎是一个很好的工具:sh (Python subprocess interface) .
看一个例子:
无耻的插件,我为此写了一个库:P https://github.com/houqp/shell.py
它现在基本上是popen和shlex的包装器 . 它还支持管道命令,因此您可以在Python中更轻松地链接命令 . 所以你可以这样做:
如果您不想测试返回值,则
subprocess.check_call
很方便 . 它会对任何错误抛出异常 .有许多不同的库允许您使用Python调用外部命令 . 对于每个库,我已经给出了描述并显示了调用外部命令的示例 . 我用作示例的命令是
ls -l
(列出所有文件) . 如果您想了解有关我列出的任何库的更多信息,并链接每个库的文档 .子进程:https://docs.python.org/3.5/library/subprocess.html
shlex:https://docs.python.org/3/library/shlex.html
os:https://docs.python.org/3.5/library/os.html
sh:https://amoffat.github.io/sh/
铅:https://plumbum.readthedocs.io/en/latest/
pexpect:https://pexpect.readthedocs.io/en/stable/
面料:http://www.fabfile.org/
特使:https://github.com/kennethreitz/envoy
命令:https://docs.python.org/2/library/commands.html
希望这可以帮助您决定使用哪个库:)
子进程允许您调用外部命令并将它们连接到它们的输入/输出/错误管道(stdin,stdout和stderr) . 子进程是运行命令的默认选择,但有时其他模块更好 .
os用于"operating system dependent functionality" . 它还可以用于使用
os.system
和os.popen
调用外部命令(注意:还有一个subprocess.popen) . 操作系统将始终运行shell,对于那些不知道如何使用subprocess.run
的人来说,它是一个简单的选择 .sh是一个子进程接口,它允许您像调用函数一样调用程序 . 如果要多次运行命令,这非常有用 .
plumbum是"script-like" Python程序的库 . 您可以像
sh
中那样调用类似函数的程序 . 如果要运行没有shell的管道,Plumbum很有用 .pexpect允许您生成子应用程序,控制它们并在其输出中查找模式 . 对于期望在Unix上使用tty的命令,这是替代子进程的更好的替代方法 .
fabric是一个Python 2.5和2.7库 . 它允许您执行本地和远程shell命令 . Fabric是在安全shell(SSH)中运行命令的简单替代方法
特使被称为"subprocess for humans" . 它被用作
subprocess
模块周围的便利包装器 .commands
包含os.popen
的包装函数,但它已从Python 3中删除,因为subprocess
是更好的选择 .该编辑基于J.F. Sebastian的评论 .
这就是我运行命令的方式 . 此代码包含您需要的所有内容
查看标准库中的subprocess module:
subprocess 与 system 的优点是它更灵活(你可以获得stdout,stderr,"real"状态代码,更好的错误处理等等) .
official documentation推荐使用 subprocess 模块替代os.system():
subprocess 文档中的“Replacing Older Functions with the subprocess Module”部分可能有一些有用的配方 .
有关 subprocess 模块的官方文档:
我通常使用:
您可以使用管道中的
stdout
数据自由地执行所需操作 . 实际上,您可以简单地省略这些参数(stdout=
和stderr=
),它的行为类似于os.system()
.还有Plumbum