我有一个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?
答案 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)
哪个有效。请注意,这需要将整个文件读入内存,这可能是真正大文件的问题。