Python 的 Popen 清理
我想使用相当于在 perl 中管道传输一些 shell 命令的 python。类似于 python 版本的 open(PIPE, "command |")。
我转到 subprocess 模块并尝试这个:
p = subprocess.Popen("zgrep thingiwant largefile", shell=True, stdout=subprocess.PIPE)
这可以像在 perl 中一样读取输出,但它不会自行清理。当我退出解释器时,我会
grep: writing output: Broken pipe
在 stderr 上吐出几百万次。我想我天真地希望这一切都会为我解决,但事实并非如此。在 p 上调用终止或终止似乎没有帮助。查看进程表,我发现这会杀死 /bin/sh 进程,但将子 gzip 留在原处以抱怨管道损坏。
这样做的正确方法是什么?
I wanted to use a python equivalent to piping some shell commands in perl. Something like the python version of open(PIPE, "command |").
I go to the subprocess module and try this:
p = subprocess.Popen("zgrep thingiwant largefile", shell=True, stdout=subprocess.PIPE)
This works for reading the output the same way I would in perl, but it doesn't clean itself up. When I exit the interpreter, I get
grep: writing output: Broken pipe
spewed all over stderr a few million times. I guess I had naively hoped all this would be taken care of for me, but that's not true. Calling terminate or kill on p doesn't seem to help. Look at the process table, I see that this kills the /bin/sh process, but leaves the child gzip in place to complain about the broken pipe.
What's the right way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
问题是
管道
已满。子进程停止,等待管道清空,但随后进程(Python 解释器)退出,破坏了管道的末尾(因此出现错误消息)。p.wait()
不会帮助你:p.communicate()
不会帮助你:p.stdout.read(num_bytes)
不会帮助你:这个故事的寓意是,对于大输出,如果您的程序试图读取数据,
subprocess.PIPE
注定会失败(在我看来,您应该能够将p.stdout.read(bytes)
放入while p.returncode is None:
循环中,但上面的警告表明这可能会死锁)。文档建议用以下内容替换 shell 管道:
请注意,
p2
直接从p1
获取其标准输入。这应该避免死锁,但考虑到上面相互矛盾的警告,谁知道。无论如何,如果最后一部分不适合您(不过,它应该),您可以尝试创建一个临时文件,写入第一次调用的所有数据,然后使用临时文件作为下一个流程的输入。
The issue is that the
pipe
is full. The subprocess stops, waiting for the pipe to empty out, but then your process (the Python interpreter) quits, breaking its end of the pipe (hence the error message).p.wait()
will not help you:p.communicate()
will not help you:p.stdout.read(num_bytes)
will not help you:The moral of the story is, for large output,
subprocess.PIPE
will doom you to certain failure if your program is trying to read the data (it seems to me that you should be able to putp.stdout.read(bytes)
into awhile p.returncode is None:
loop, but the above warning suggests that this could deadlock).The docs suggest replacing a shell pipe with this:
Notice that
p2
is taking its standard input directly fromp1
. This should avoid deadlocks, but given the contradictory warnings above, who knows.Anyway, if that last part doesn't work for you (it should, though), you could try creating a temporary file, writing all data from the first call to that, and then using the temporary file as input to the next process.
打开管道后,您可以使用命令输出:
p.stdout
:After you open the pipe, you can work with the command output:
p.stdout
:你是如何执行这个过程的?
正确的方法是使用
查看文档了解更多详细信息。
How did you executed this process?
Proper way is to use
See docs for more details.
您需要
等待
该过程完成:或者,您可以捕获程序的标准输出(如您所拥有的),也许还有它的标准错误,然后调用
communicate
:You need to
wait
for the process to finish:Alternatively, you can capture the program's standard output (as you have), and perhaps its standard error, and then call
communicate
: