Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python';斯波本清理_Python_Popen_Resource Cleanup - Fatal编程技术网

Python';斯波本清理

Python';斯波本清理,python,popen,resource-cleanup,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

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

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

p = subprocess.Popen("zgrep thingiwant largefile", shell=True, stdout=subprocess.PIPE)
这与我在perl中读取输出的方式相同,但它不会自行清理。当我退出口译员时,我得到

grep: writing output: Broken pipe
在斯特德河上喷了几百万次。我想我天真地希望这一切都能为我解决,但事实并非如此。在p上调用terminate或kill似乎没有帮助。查看进程表,我看到这会终止/bin/sh进程,但会留下子gzip来抱怨管道破裂


正确的方法是什么?

您是如何执行此过程的

正确的方法是使用

p.communicate()

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

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

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

您需要等待流程完成:

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()

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

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

警告如果子进程向stdout或stderr管道生成足够的输出,从而阻止等待操作系统管道缓冲区接受更多数据,则此操作将死锁。使用
communicate()
来避免这种情况

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

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

p.stdout.read(num_字节)
对您没有帮助:

警告使用
communicate()
而不是
.stdin.write
.stdout.read
.stderr.read
避免由于任何其他操作系统管道缓冲区填满并阻塞子进程而导致死锁

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

文件建议将壳管更换为:

p1 = Popen(["zgrep", "thingiwant", "largefile"], stdout=PIPE)
p2 = Popen(["processreceivingdata"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]
请注意,
p2
直接从
p1
获取其标准输入。这应该可以避免僵局,但鉴于上述相互矛盾的警告,谁知道呢


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

即使我从未与该进程通信,也会发生这种情况。仅仅创建对象p然后退出解释器就导致了这个问题。是的,如果我没有记错的话,Popen会执行这个命令
communicate()
然后等待进程结束、刷新缓冲区等。另请参见
check\u call()
。是否在子进程
p
完成之前退出解释器?