2

我有几个subprocess实例我想串成一个管道,但我被卡住了,想征求意见。

例如,模仿:

cat data | foo - | bar - > result

或者:

foo - < data | bar - > result

...我首先尝试了以下,它挂起:

import subprocess, sys

firstProcess = subprocess.Popen(['foo', '-'], stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE)
secondProcess = subprocess.Popen(['bar', '-'], stdin=firstProcess.stdout,
                                 stdout=sys.stdout)

for line in sys.stdin:
    firstProcess.stdin.write(line)
    firstProcess.stdin.flush()

firstProcess.stdin.close()
firstProcess.wait()

我的第二次尝试使用subprocess带有参数的一个实例,该实例shell=True有效:

import subprocess, sys

pipedProcess = subprocess.Popen(" ".join(['foo', '-', '|', 'bar', '-']),
                                stdin=subprocess.PIPE, shell=True)

for line in sys.stdin:
    pipedProcess.stdin.write(line)
    pipedProcess.stdin.flush()

pipedProcess.stdin.close()
pipedProcess.wait()

subprocess第一种链式方法我做错了什么?我读到最好不要使用shell=True,我很好奇我在第一种方法中做错了什么。谢谢你的建议。

编辑

我修正了我的问题中的一个错字并修正stdinsecondProcess. 它仍然挂起。

我也尝试删除firstProcess.wait()解决挂起的问题,但随后我得到一个 0 字节文件作为result.

我会坚持使用pipedProcess,因为它工作正常。但是,如果有人知道为什么第一个设置挂起或生成一个 0 字节文件作为输出,我也很想知道为什么。

4

2 回答 2

2

shell=True之所以有效,是因为您要求外壳程序解释您的整个命令行并自行处理管道。就好像您foo - | bar -直接在 shell 中键入一样。

(这也是使用它可能不安全的原因shell=True;有很多方法可以欺骗 shell 做坏事,如果您直接将命令和参数作为不受任何解析的列表传递,则不会发生这种情况中介。)

于 2013-03-12T23:50:06.537 回答
1

要修复第一个示例,请foo_process.stdout.close()按照文档建议添加. 以下代码模拟foo - | bar -命令:

#!/usr/bin/python
from subprocess import Popen, PIPE

foo_process = Popen(['foo', '-'], stdout=PIPE)
bar_process = Popen(['bar', '-'], stdin=foo_process.stdout)
foo_process.stdout.close() # allow foo to know if bar ends
bar_process.communicate()  # equivalent to bar_process.wait() in this case  

除非它们与 , 不同,否则您不需要在此处显式使用sys.stdin, 。sys.stdoutsys.__stdin__sys.__stdout__

模拟foo - < data | bar - > result命令:

#!/usr/bin/python
from subprocess import Popen, PIPE

with open('data','rb') as input_file, open('result', 'wb') as output_file:
    foo = Popen(['foo', '-'], stdin=input_file, stdout=PIPE)
    bar = Popen(['bar', '-'], stdin=foo.stdout, stdout=output_file)
    foo.stdout.close() # allow foo to know if bar ends
bar.wait()

如果您想将修改后的输入逐行提供给foo进程,即模拟python modify_input.py | foo - | bar -命令:

#!/usr/bin/python
import sys
from subprocess import Popen, PIPE

foo_process = Popen(['foo', '-'], stdin=PIPE, stdout=PIPE)
bar_process = Popen(['bar', '-'], stdin=foo_process.stdout)
foo_process.stdout.close() # allow foo to know if bar ends
for line in sys.stdin:
    print >>foo_process.stdin, "PY", line, # modify input, feed it to `foo`
foo_process.stdin.close() # tell foo there is no more input
bar_process.wait()
于 2013-03-13T00:17:26.397 回答