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

smc*_*mci 5 python subprocess glob

在子进程调用中,我想使用shell = True,以便它对路径名(下面的代码)进行通配,但是这会产生令人讨厌的副作用,即subprocess生成子进程(必须是`communication()d/poll ()ed/wait()ed/terminate()d/kill()ed/whatevah).

(是的我知道globing也可以用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.在我的情况下,动机是命令是固定的,但我可能想要多次调用它有区别文件规范).

Cha*_*ffy 7

首先 - 将数组传递给:

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

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

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

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

一个简单的方法,因为你有shell=True:

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

...交替:

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='')
Run Code Online (Sandbox Code Playgroud)

...这将确保stdinPython代码中的空,而不是依赖于shell.