我如何在Python中命名一个外部命令,就好像我把它写在一个<unk>或命令中?


当前回答

假设你想从一个 CGI 脚本开始一个漫长的任务,也就是说,孩子的过程应该比 CGI 脚本执行过程更长。

从子过程模块文档的经典例子是:

import subprocess
import sys

# Some code here

pid = subprocess.Popen([sys.executable, "longtask.py"]) # Call subprocess

# Some more code here

我的目标平台是FreeBSD,但开发是在Windows上,所以我首先面对了Windows上的问题。

在Windows(Windows XP)上,父母过程不会完成,直到 longtask.py 完成了工作。 这不是你想要的 CGI 脚本. 问题不是具体的 Python; 在 PHP 社区,问题是相同的。

解决方案是将 DETACHED_PROCESS Process Creation Flag 转移到 Windows API 中的 CreateProcess 功能。 如果您安装了 pywin32,您可以从 win32 过程模块中导入旗帜,否则您应该自己定义:

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid

pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

我没有在其他平台上检查代码,也不知道FreeBSD的行为原因,如果有人知道的话,请分享你的想法。

其他回答

典型的实施:

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()

事实上,你可以简单地忽略这些参数(stdout=和stderr=)并将像os.system()一样行事。

我总是使用纺织品来做这些事情,这里是一个演示代码:

from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, )

但这似乎是一个很好的工具:sh(Python子处理界面)。

看看一个例子:

from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)

步骤1:添加模块

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

步骤2:呼叫外部命令

import subprocess

result = subprocess.run(["ls"], capture_output=True)
print(result.stdout)

提示: shlex.split() 方法可以用来将简单的 shell 命令分解到单个论点,但它可能不会正确地与包含管道符号的更长和更复杂的命令一起工作,这可能会使漏洞变得困难。

安全影响:在运行外部命令时,您应该小心正确逃避包含特殊字符的任何论点,因为它们可能会被阴影以意想不到的方式解释。


子过程模块提供了更强大的设施,以便扫描新过程并获取其结果;使用该模块,最好使用此功能。 请参见子过程模块部分的替代老功能,在子过程文档中找到一些有用的食谱。


注意: 在 Python 3.4 或更高版本中,使用 subprocess.call 而不是.run:

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

如果您使用 Python 3.5 +,请使用 subprocess.run()。

使用 subprocess.call:

from subprocess import call

# Using list
call(["echo", "Hello", "world"])

# Single string argument varies across platforms so better split it
call("echo Hello world".split(" "))

还有不同的方式来处理返回代码和错误,你可能想打破输出,并提供新的输入(在预期类型的风格)。或者你将需要重新引导标准输入,标准输出和标准错误运行在不同的tty(例如,当使用GNU屏幕)。

因此,这里是我们写的Python模块,可以处理你想要的几乎任何东西,如果没有,它是非常灵活的,所以你可以轻松地扩展它:

它不单独工作,需要一些我们的其他工具,并在过去的几年里获得了很多专门的功能,所以它可能不是一个下降的替代品,但它可以给你很多关于如何运行命令的Python内部工作以及如何处理某些情况的想法。