用shell = True纠正子进程的咒语以获得输出而不是挂起

时间:2012-03-26 22:16:23

标签: python subprocess glob

在子进程调用中,我想使用 shell = True ,以便它对路径名(下面的代码)进行通配,但是this has the annoying side-effect of making subprocess spawn a child process(必须是` ()d / poll()ed / wait()ed / terminate()d / kill()ed / whatevah )。

(是的我知道可以使用fnmatch / glob完成全局操作,但是请向我展示子进程的'正确'用法,即获得stdout的最小咒语并停止子进程。)

这样可以正常工作(返回输出):

  

subprocess.check_output(['/usr/bin/wc','-l','[A-Z]*/[A-Z]*.F*'], shell=False)

但是这会挂起

  

subprocess.check_output(['/usr/bin/wc','-l','[A-Z]*/[A-Z]*.F*'], shell=True)

(PS:严重恶化的是你不能告诉你想要的子进程一些但不是所有 shell功能,例如通配但不产生。我认为这是一个值得的PEP在那里,如果有人关心评论,即传入一个布尔元组,或二进制标志的

(PPS:你是否通过 subprocess...(cmdstring.split() or [...]) 的成语只是一个微不足道的惯用语。我说番茄,你说tomay-to。在我的情况下,动机就是命令是固定的,但我可能想用不同的文件规范多次调用它。)

1 个答案:

答案 0 :(得分:6)

首先关闭 - 将数组传递给:

非常简单
subprocess.check_output(['/usr/bin/wc','-l','A-Z*/A-Z*.F*'], shell=True)

...因为这只是在没有参数的情况下运行wc,在shell中也传递参数-lA-Z*/A-Z*.F*作为参数(对shell而不是wc )。相反,你想要:

subprocess.check_output('/usr/bin/wc -l A-Z*/A-Z*.F*', shell=True)

在纠正之前,这会挂起,因为wc没有参数并且正在从stdin读取。我建议确保stdin在关闭时传递,而不是传递你的Python程序stdin(默认行为)。

这是一种简单的方法,因为您有shell=True

subprocess.check_output(
    '/usr/bin/wc -l A-Z*/A-Z*.F* </dev/null',
    shell=True)

...交替:

p = subprocess.Popen('/usr/bin/wc -l A-Z*/A-Z*.F*', shell=True,
                     stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None)
(output, _) = p.communicate(input='')

...这将确保Python代码中的空stdin而不是依赖shell。