我正在运行以下版本的Python:
$ /usr/bin/env python --version
Python 2.5.2
Run Code Online (Sandbox Code Playgroud)
我运行以下Python代码将数据从子子进程写入标准输出,并将其读入一个名为的Python变量metadata:
# 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
Run Code Online (Sandbox Code Playgroud)
用例如下,从上述代码片段中提取前十行标准输出:
$ extractMetadata.py | head
Run Code Online (Sandbox Code Playgroud)
如果我输入head,awk,grep等,则会出现错误.
该脚本以以下错误结束:
close failed: [Errno 32] Broken pipe
Run Code Online (Sandbox Code Playgroud)
我本以为关闭管道就足够了,但显然事实并非如此.
嗯。我之前见过 subprocess + gzip 的一些“Broken pipeline”奇怪现象。我从来没有弄清楚为什么会发生这种情况,但通过改变我的实现方法,我能够避免这个问题。看起来你只是想使用后端 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)
Run Code Online (Sandbox Code Playgroud)