Python 子进程模块,如何向管道命令系列中的第一个提供输入?
我正在尝试使用Python的子进程模块。我需要的是将输入发送到第一个进程,其输出成为第二个进程的输入。 情况基本上和这里文档中给出的例子几乎一样: http://docs.python.org/library/subprocess.html#replacing -shell-管道 除了我需要提供第一个命令的输入。 这是复制的示例:
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()
我希望我已经足够清楚了,感谢您的帮助。
I am trying to use Python's subprocess module. What I require is to send input to the first process whose output becomes the input of the second process.
The situation is basically almost the same as the example given in the documentation here:
http://docs.python.org/library/subprocess.html#replacing-shell-pipeline
except that I need to provide input the first command.
Here is that example copied:
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]
If we change the first line to:
p1 = Popen(["cat"], stdout=PIPE, stdin=PIPE)
How do I provide the input string to the process?
If I attempt it by changing the final line to:
output = p2.communicate(input=inputstring)[0]
This doesn't work.
I do have a working version, which just stores the output of the first command in a string and then passes that to the second command. This isn't terrible as there is essentially no concurrency that can be exploited (in my actual use case the first command will exit rather quickly and produce all of its output at the end).
Here is the working version in full:
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()
I hope I've been clear enough, thanks for any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您这样做,
您应该执行
p1.communicate("Your Input to the p1")
,这将流经 PIPE。标准输入是进程的输入,您应该仅与其进行通信。
给出的程序绝对没问题,看起来没有问题。
If you do
You should do
p1.communicate("Your Input to the p1")
and that will flow through the PIPE.The stdin is the process's input and you should communicate to that only.
The program which have given is absolutely fine, there seems no problem with that.
我假设 cat 、 grep 只是示例命令,否则您可以使用没有子进程的纯 Python 解决方案,例如:
或者如果您想使用 grep :
您可以将第一个命令的输出传递给第二个命令,而无需先将其存储在字符串中:
如果您不想将所有输入/输出存储在内存中;您可能需要线程(以块的方式读取/写入而不阻塞)或选择循环(适用于 POSIX)。
如果有多个命令,则按照 @Troels Folke 的建议直接使用 shell 或使用 < a href="https://stackoverflow.com/a/16709666/4279">一个库,例如
plumbum
,它隐藏了手动模拟 shell 的所有血腥细节。I assume that
cat
,grep
are just example commands otherwise you could use a pure Python solution without subprocesses e.g.:Or if you want to use
grep
:You can pass the output of the first command to the second one without storing it in a string first:
If you don't want to store all input/output in memory; you might need threads (to read/write in chunks without blocking) or a select loop (works on POSIX).
If there are multiple commands, it might be more readable just to use the shell directly as suggested by @Troels Folke or use a library such as
plumbum
that hides all the gory details of emulating the shell by hand.嗯,为什么不加入一点(ba)sh呢? :-)
但请注意:
这只适用于使用 Bourne Shell 兼容 shell 的系统(如大多数 *nix'es)
Usign shell=True 并将用户输入放入命令字符串中是一个坏主意,除非您首先转义用户输入。阅读子流程文档 -> “常用参数”了解详细信息。
这是丑陋的,不可移植的,非Pythonic的等等......
编辑:
不过,如果您只想使用
grep
,则无需使用cat
。只需将输入直接提供给 grep,或者更好的是,使用 python 正则表达式。Hmm, why not mix in a bit of (ba)sh? :-)
BEWARE though:
This only works on systems that use a Bourne Shell compatible shell (like most *nix'es)
Usign shell=True and putting user input in the command string is a bad idea, unless you escape the user input first. Read the subprocess docs -> "Frequently Used Arguments" for details.
This is ugly, non portable, non pythonic and so on...
EDIT:
There is no need to use
cat
though, if all you want to do isgrep
. Just feed the input directly to grep, or even better, use python regular expressions.我遇到了类似的问题,我想要几个管道
Popen
。这对我有用:
但是,带有线程的 @jfs 解决方案 似乎更强大。
I faced a similar problem where I wanted to have several piped
Popen
.This worked for me:
However, the @jfs solution with threads seems more robust.