“&>”的奇怪行为在子进程Popen中

时间:2017-10-22 19:28:46

标签: python bash

我注意到了“&>” subprocess.Popen()调用中的运算符立即提供返回代码,即使在直观上不应该的情况下也是如此。举例说明:

>>> import subprocess
>>> a = subprocess.Popen("sleep 5 > a.txt", shell = True)
>>> print(a.poll()) # immediately try printing
None
>>> print(a.poll()) # wait 5 seconds
0
>>> a = subprocess.Popen("sleep 5 &> a.txt", shell = True)
>>> print(a.poll()) # immediately try printing
0
>>> a = subprocess.Popen("sleep 5 > a.txt 2>&1", shell = True) # this should be the same as using &>
>>> print(a.poll()) # immediately try printing
None
>>> print(a.poll()) # wait 5 seconds
0

我在Python 3.5.2上运行它。我的机器默认运行bash。

有谁知道为什么子进程不支持正确的“&>”这里的行为?

2 个答案:

答案 0 :(得分:2)

这是因为&> bashism Popen默认情况下/bin/sh使用shell=True

来自subprocess.Popen docs

  

executable参数指定要执行的替换程序。这很少需要。当shell=False时,可执行文件替换args指定的程序执行。但是,原始args仍然传递给程序。大多数程序将args指定的程序视为命令名,然后可以与实际执行的程序不同。在POSIX上,args名称成为ps等实用程序中可执行文件的显示名称。 如果shell=True,在POSIX上,executable参数指定默认/bin/sh的替换shell。

修复方法是明确指定executable参数,例如:

subprocess.Popen("sleep 5 &> a.txt", shell=True, executable='/bin/bash')

答案 1 :(得分:2)

您的默认登录 shell为bash。但是,subprocess.Popen使用系统默认shell /bin/sh,它无法识别&>运算符。如果您想强制它使用bash,请使用executable选项:

a = subprocess.Popen("sleep 5 &> a.txt", shell=True, executable="/bin/bash")

或者,您可以在Python中自己处理重定向:

with open("a.txt", "w") as fh:
    a = subprocess.Popen(["sleep", "5"], stdout=fh, stderr=fh)