Python gzip拒绝读取未压缩的文件



我似乎记得Python gzip模块以前允许您透明地读取非gzip文件。这真的很有用,因为它允许读取输入文件,无论它是否被压缩。你根本不用担心。

现在,我得到一个IOError异常(在Python 2.7.5):

   Traceback (most recent call last):
  File "tst.py", line 14, in <module>
    rec = fd.readline()
  File "/sw/lib/python2.7/gzip.py", line 455, in readline
    c = self.read(readsize)
  File "/sw/lib/python2.7/gzip.py", line 261, in read
    self._read(readsize)
  File "/sw/lib/python2.7/gzip.py", line 296, in _read
    self._read_gzip_header()
  File "/sw/lib/python2.7/gzip.py", line 190, in _read_gzip_header
    raise IOError, 'Not a gzipped file'
IOError: Not a gzipped file

如果有人有一个巧妙的技巧,我想听听。是的,我知道如何捕获异常,但是我发现首先读取一行,然后关闭文件并再次打开它相当笨拙。

最好的解决方案是在libmagic中使用https://github.com/ahupp/python-magic之类的东西。你根本无法避免至少读取一个头来标识一个文件(除非你隐式地信任文件扩展名)

如果您觉得很简朴,那么标识gzip(1)文件的神奇数字是前两个字节为0x1f 0x8b。

In [1]: f = open('foo.html.gz')
In [2]: print `f.read(2)`
'x1fx8b'

gzip。open只是GzipFile的包装,你可以有这样一个函数,它只返回正确的对象类型,这取决于源文件是什么,而不需要打开文件两次:

#!/usr/bin/python
import gzip
def opener(filename):
    f = open(filename,'rb')
    if (f.read(2) == 'x1fx8b'):
        f.seek(0)
        return gzip.GzipFile(fileobj=f)
    else:
        f.seek(0)
        return f

也许您在考虑zless或zgrep,它们可以打开压缩或未压缩的文件而不会报错。

你能相信文件名以。gz结尾吗?

if file_name.endswith('.gz'):
    opener = gzip.open
else:
    opener = open
with opener(file_name, 'r') as f:
    ...

读取前四个字节。如果前三个字节是0x1f、0x8b、0x08,并且第四个字节的前三个位是零,那么从这四个字节开始启动gzip压缩。否则,写出这四个字节并继续透明地读取。

您应该仍然有一个笨拙的解决方案来备份它,这样如果gzip读取失败,那么就可以透明地备份和读取。但是不太可能让前四个字节很好地模拟gzip文件,而不是gzip文件。

您可以使用fileinput(files, openhook=fileinput.hook_compressed)透明地遍历文件

最新更新