使用gzip文件作为stdin用于使用subprocess.call执行的命令

时间:2017-04-29 20:49:46

标签: python gzip

我有一个python脚本,使用subprocess.call()执行多个命令。我需要使用stdin将数据从gzip压缩文件传递给其中一个命令,但无论我做什么,该命令显然都会获取gzip压缩数据。

我认为应该这样做:

import gzip
from subprocess import call

in_fname = 'test.gz'
out_fname = 'test.txt'

gz = gzip.open(in_fname, 'rb')
txt = open(out_fname, 'w')

call(['cat'], stdin=gz, stdout=txt)

但最后,'test.txt'被压缩,并且与gzip压缩输入文件的大小完全相同。

如果我拨打gz.read(),我会按预期获得正确的解压缩数据。如何将gzip压缩文件用作stdin?

1 个答案:

答案 0 :(得分:0)

在做了一些研究之后,问题的根源在于你的操作系统不知道gzip文件的文件句柄有什么特别之处。基本上,gzip提供了“类文件”接口,但子进程(在这种情况下为cat)并不知道这是一个需要解压缩的特殊文件。因此,它只是为字节读取文件字节并打印出它读取的乱码。

我的下一个想法是在python中读取整个文件(它知道它已经压缩并将其解压缩)然后将字符串传递给子进程。我把解压缩的内容包装在一个StringIO对象中,但事实证明不起作用。另一个答案(Use StringIO as stdin with Popen)提到了对subprocess的稍微不同的调用:

import gzip
from subprocess import Popen, PIPE

in_fname = 'test.gz'
out_fname = 'test.txt'

with gzip.open(in_fname, 'rb') as f:
  gz = f.read()
txt = open(out_fname, 'w')


process = Popen(['cat'], stdin=PIPE, stdout=txt)
process.communicate(gz)

哪个有效。请注意,这需要将整个文件读入内存,这可能是真正大文件的问题。