Python子流程模块,如何为第一个管道命令系列提供输入?
我正在尝试使用Python的子流程模块。我需要的是将输入发送到第一个进程,其输出成为第二个进程的输入。 情况基本上与此处文档中给出的示例相同: 除了我需要为第一个命令提供输入。 下面是复制的示例:Python子流程模块,如何为第一个管道命令系列提供输入?,python,pipe,subprocess,Python,Pipe,Subprocess,我正在尝试使用Python的子流程模块。我需要的是将输入发送到第一个进程,其输出成为第二个进程的输入。 情况基本上与此处文档中给出的示例相同: 除了我需要为第一个命令提供输入。 下面是复制的示例: p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 e
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]
如果我们将第一行更改为:
p1 = Popen(["cat"], stdout=PIPE, stdin=PIPE)
如何向流程提供输入字符串?
如果我尝试将最后一行更改为:
output = p2.communicate(input=inputstring)[0]
这不管用
我有一个工作版本,它只是将第一个命令的输出存储在一个字符串中,然后将其传递给第二个命令。这并不可怕,因为基本上没有可以利用的并发性(在我的实际用例中,第一个命令将很快退出,并在最后生成其所有输出)。
以下是完整的工作版本:
import subprocess
simple = """Writing some text
with some lines in which the
word line occurs but others
where it does
not
"""
def run ():
catcommand = [ "cat" ]
catprocess = subprocess.Popen(catcommand,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(catout, caterr) = catprocess.communicate(input=simple)
grepcommand = [ "grep", "line" ]
grepprocess = subprocess.Popen(grepcommand,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(grepout, greperr) = grepprocess.communicate(input=catout)
print "--- output ----"
print grepout
print "--- error ----"
print greperr
if __name__ == "__main__":
run()
我希望我已经说得够清楚了,谢谢你的帮助。如果你这样做的话
from subprocess import Popen, PIPE
p1 = Popen(["cat"], stdout=PIPE, stdin=PIPE)
您应该执行p1。通信(“您对p1的输入”)
,这将流经管道。
stdin是流程的输入,您应该只与它通信
给出的程序非常好,似乎没有问题。嗯,为什么不混合一点(ba)sh?:-) 但要注意:
- 这只适用于使用Bourne Shell兼容Shell的系统(如大多数*nix'es)
- Usign shell=True,将用户输入放在命令字符串中是个坏主意,除非首先转义用户输入。有关详细信息,请阅读子流程文档->“常用参数”
- 这是丑陋的,不可移植的,非蟒蛇的等等
如果您只想做
grep
,则无需使用cat
。只需将输入直接输入到grep,或者更好地使用python正则表达式。我假设cat
,grep
只是示例命令,否则您可以使用纯python解决方案而不使用子流程,例如:
for line in simple.splitlines():
if "line" in line:
print(line)
或者如果您想使用grep
:
from subprocess import Popen, PIPE
output = Popen(['grep', 'line'], stdin=PIPE, stdout=PIPE).communicate(simple)[0]
print output,
您可以将第一个命令的输出传递给第二个命令,而无需先将其存储在字符串中:
from subprocess import Popen, PIPE
from threading import Thread
# start commands in parallel
first = Popen(first_command, stdin=PIPE, stdout=PIPE)
second = Popen(second_command, stdin=first.stdout, stdout=PIPE)
first.stdout.close() # notify `first` if `second` exits
first.stdout = None # avoid I/O on it in `.communicate()`
# feed input to the first command
Thread(target=first.communicate, args=[simple]).start() # avoid blocking
# get output from the second command at the same time
output = second.communicate()[0]
print output,
如果您不想在内存中存储所有输入/输出;您可能需要线程(在块中读/写而不阻塞)或选择循环(在POSIX上工作)
如果有多个命令,只需按照或使用的建议直接使用shell可能更具可读性。您好,谢谢您的回答,我想我只需保留给定的程序即可。我认为使用字符串来存储第一个过程的结果可能效率很低。不,不是这样。将输出存储为字符串是很正常的。
from subprocess import Popen, PIPE
from threading import Thread
# start commands in parallel
first = Popen(first_command, stdin=PIPE, stdout=PIPE)
second = Popen(second_command, stdin=first.stdout, stdout=PIPE)
first.stdout.close() # notify `first` if `second` exits
first.stdout = None # avoid I/O on it in `.communicate()`
# feed input to the first command
Thread(target=first.communicate, args=[simple]).start() # avoid blocking
# get output from the second command at the same time
output = second.communicate()[0]
print output,