Python的Popen清理

2024-09-28 22:22:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我想使用相当于在perl中管道化一些shell命令的python。类似于open(PIPE,“command |”)的python版本。

我转到子流程模块并尝试执行以下操作:

p = subprocess.Popen("zgrep thingiwant largefile", shell=True, stdout=subprocess.PIPE)

这与我在perl中读取输出的方式相同,但它不会自行清除。当我离开口译员时

grep: writing output: Broken pipe

喷发了几百万次。我想我天真地希望这一切都能得到照顾,但事实并非如此。在p上调用terminate或kill似乎没有帮助。看看process表,我发现这会终止/bin/sh进程,但会留下子gzip来抱怨管道损坏。

正确的方法是什么?


Tags: 模块命令版本true流程openshellcommand
3条回答

打开管道后,可以使用命令输出:p.stdout

for line in p.stdout:
    # do stuff
p.stdout.close()

你是怎么执行这个程序的?

正确的方法是使用

p.communicate()

有关详细信息,请参见文档。

问题是pipe已满。子进程停止,等待管道清空,但随后您的进程(Python解释器)退出,中断其管道末端(因此出现错误消息)。

p.wait()不会帮助您:

Warning This will deadlock if the child process generates enough output to a stdout or stderr pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.

http://docs.python.org/library/subprocess.html#subprocess.Popen.wait

p.communicate()不会帮助您:

Note The data read is buffered in memory, so do not use this method if the data size is large or unlimited.

http://docs.python.org/library/subprocess.html#subprocess.Popen.communicate

p.stdout.read(num_bytes)不会帮助您:

Warning Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.

http://docs.python.org/library/subprocess.html#subprocess.Popen.stdout

这个故事的寓意是,对于大输出来说,subprocess.PIPE如果您的程序试图读取数据,那么它将注定失败(在我看来,您应该能够将p.stdout.read(bytes)放入一个while p.returncode is None:循环中,但上面的警告表明这可能会死锁)。

文档建议用以下内容替换shell管道:

p1 = Popen(["zgrep", "thingiwant", "largefile"], stdout=PIPE)
p2 = Popen(["processreceivingdata"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

注意,p2直接从p1获取其标准输入。这应该可以避免死锁,但是考虑到上面相互矛盾的警告,谁知道

无论如何,如果最后一部分对您不起作用(但是它应该应该),您可以尝试创建一个临时文件,将第一次调用中的所有数据写入该文件,然后将该临时文件用作下一个进程的输入。

相关问题 更多 >