Python Popen清理

时间:2010-04-07 20:15:00

标签: python popen resource-cleanup

我想使用python等效于在perl中管理一些shell命令。像python版本的open(PIPE,“command |”)。

我转到子进程模块并试试这个:

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

这适用于以与perl相同的方式读取输出,但它不能自我清理。当我退出翻译时,我得到了

grep: writing output: Broken pipe
几百万次喷出stderr。我想我天真地希望所有这些都能得到照顾,但事实并非如此。在p上调用终止或终止似乎没有帮助。看一下进程表,我看到这会杀死/ bin / sh进程,但让子进程gzip抱怨管道坏了。

这样做的正确方法是什么?

4 个答案:

答案 0 :(得分:9)

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

p.wait()对您没有帮助:

  

警告如果子进程为stdout或stderr管道生成足够的输出,使其阻塞等待OS管道缓冲区接受更多数据,则会发生死锁。使用communicate()来避免这种情况。

     

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

p.communicate()对您没有帮助:

  

注意读取的数据缓冲在内存中,因此如果数据量很大或无限制,请不要使用此方法。

     

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

p.stdout.read(num_bytes)对您没有帮助:

  

警告使用communicate()而非.stdin.write.stdout.read.stderr.read以避免因任何其他操作系统管道缓冲区填满而导致的死锁并阻止子进程。

     

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获取标准输入。这个应该避免死锁,但鉴于上面的矛盾警告,谁知道

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:0)

你是如何执行这个过程的?

正确的方法是使用

p.communicate()

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

答案 3 :(得分:0)

您需要wait才能完成整个过程:

import subprocess
p = subprocess.Popen("cat /mach_kernel", shell=True)
p.wait()

或者,您可以捕获程序的标准输出(如您所示),也许是标准错误,然后调用communicate

import subprocess
p = subprocess.Popen("cat /mach_kernel", shell=True,
                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()