我正在运行以下版本的 Python:
$ /usr/bin/env python --version
Python 2.5.2
我正在运行以下 Python 代码,将子进程中的数据写入标准输出,并将其读入名为 metadata
的 Python 变量:
# Extract metadata (snippet from extractMetadata.py)
inFileAsGzip = "%s.gz" % inFile
if os.path.exists(inFileAsGzip):
os.remove(inFileAsGzip)
os.symlink(inFile, inFileAsGzip)
extractMetadataCommand = "bgzip -c -d -b 0 -s %s %s" % (metadataRequiredFileSize, inFileAsGzip)
metadataPipes = subprocess.Popen(extractMetadataCommand, stdin=None, stdout=subprocess.PIPE, shell=True, close_fds=True)
metadata = metadataPipes.communicate()[0]
metadataPipes.stdout.close()
os.remove(inFileAsGzip)
print metadata
用例如下,从上述代码片段中提取前十行标准输出:
$ extractMetadata.py | head
如果我通过管道输入 head、awk、grep 等,就会出现错误。
脚本以以下错误结束:
close failed: [Errno 32] Broken pipe
我原以为关闭管道就足够了,但显然情况并非如此。
最佳答案
嗯。我之前已经看到 subprocess + gzip 有一些“破管”的奇怪之处。我从来没有弄清楚为什么会这样,但是通过改变我的实现方法,我能够避免这个问题。看起来您只是在尝试使用后端 gzip 进程来解压缩文件(可能是因为 Python 的内置模块非常慢……不知道为什么,但确实如此)。
您可以不使用 communicate()
,而是将进程视为完全异步的后端,并在输出到达时读取它。当流程结束时,子流程模块会为您清理一切。以下代码片段应提供相同的基本功能,而不会出现任何损坏的管道问题。
import subprocess
gz_proc = subprocess.Popen(['gzip', '-c', '-d', 'test.gz'], stdout=subprocess.PIPE)
l = list()
while True:
dat = gz_proc.stdout.read(4096)
if not d:
break
l.append(d)
file_data = ''.join(l)
关于python - 获得所需数据后,如何关闭 Python 2.5.2 Popen 子进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3861087/