Python 如何判断文件是否是gzip压缩的?

Python 如何判断文件是否是gzip压缩的?,python,compression,gzip,Python,Compression,Gzip,我有一个Python程序,它将文本文件作为输入。但是,其中一些文件可能是gzip压缩的 是否有一种跨平台、可从Python使用的方法来确定文件是否经过gzip压缩 以下是可靠的还是普通的文本文件“偶然”看起来像gzip,足以让我得到误报 try: gzip.GzipFile(filename, 'r') # compressed # ... except: # not compressed # ... gzip压缩文件的格式为1f 8b。虽然这方面的测试

我有一个Python程序,它将文本文件作为输入。但是,其中一些文件可能是gzip压缩的


是否有一种跨平台、可从Python使用的方法来确定文件是否经过gzip压缩

以下是可靠的还是普通的文本文件“偶然”看起来像gzip,足以让我得到误报

try:
    gzip.GzipFile(filename, 'r')
    # compressed
    # ...
except:
    # not compressed
    # ...
gzip压缩文件的格式为
1f 8b
。虽然这方面的测试不是100%可靠,但“普通文本文件”以UTF-8中的这两个字节开头的可能性很小,甚至是不合法的

但通常gzip压缩文件的后缀是
.gz
。即使是
gzip(1)
本身也无法在没有它的情况下解压文件,除非您
--强制它解压。您可以想象使用它,但是您仍然必须处理一个可能的IOError(在任何情况下都必须处理)

这种方法的一个问题是,
gzip.GzipFile()
在向其提供未压缩文件时不会引发异常。只有稍后的
read()
才会显示。这意味着,您可能需要实现一些程序逻辑两次。丑陋。

导入模块。 它可以自动猜测您拥有的文件类型,以及文件是否经过压缩

i、 e

返回:


('text/plain','gzip')

在python3中似乎不太好用

import mimetypes
filename = "./datasets/test"

def file_type(filename):
    type = mimetypes.guess_type(filename)
    return type
print(file_type(filename))
返回(无,无) 但是从unix命令“File”

:~>文件数据集/测试 datasets/test:gzip压缩数据,是来自Unix的“iostat_collection”,最后修改时间:Thu Jan 29 07:09:34 2015

“是否有跨平台的、可从Python使用的方法来确定文件是否是gzip压缩的?”

被接受的答案让我找到了相当可靠的解决方案(测试前两个字节是否为
1f8b
),但没有说明如何在Python中实际做到这一点。以下是一种可能的方法:

def is_gz_file(filepath):
    with open(filepath, 'rb') as test_f:
        return test_f.read(2) == b'\x1f\x8b'

gzip
如果不是gzip文件,它本身将引发一个
OSError

>>> with gzip.open('README.md', 'rb') as f:
...     f.read()
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 276, in read
    return self._buffer.read(size)
  File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 463, in read
    if not self._read_gzip_header():
  File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 411, in _read_gzip_header
    raise OSError('Not a gzipped file (%r)' % magic)
OSError: Not a gzipped file (b'# ')
测试gzip文件的安全性是唯一可靠的方法。然而,从python3.7开始,就不再需要自己比较字节了。gzip模块将为您比较字节,如果它们不匹配,则引发异常

从python3.7开始,这是有效的

导入gzip
使用gzip.open(输入_文件'r')作为fh:
尝试:
fh.read(1)
除操作错误外:
print('input_file不是OSError指定的有效gzip文件')
从python3.8开始,这也适用于:

导入gzip
使用gzip.open(输入_文件'r')作为fh:
尝试:
fh.read(1)
除了gzip.badgzip文件:
打印('BadGzipFile'的输入文件不是有效的gzip文件)

只是一个小提示。。。永远不要依赖文件结尾。如何操作,请参见hop的答案。@Helper:我不确定(请参见我的编辑)。您仍然需要处理一个可能的IOError,但是在我看来,没有后缀的gzip压缩文件被破坏了……很难调用:)gzip压缩文件通常具有.gz文件扩展名(事实上,我认为我从未见过.gzip扩展名),但无论如何,依靠文件扩展名来测试文件类型通常是不安全的。是吗?-gzip C库将透明地读取未压缩的文件。虽然它会写未压缩的文件,但它会通过CRC代码来允许“gzip-t”(我被抓住过一次)@Martin:它会:$gunzip foo gzip:foo:unknown suffix--忽略c'library'gzip,即gzip open/gzread/等将透明地读取未压缩的文件。它们有一个opencompression=none模式,该模式不会写入未更改的平面文件。关于扩展名。您还必须检查相对常见的
.tgz
扩展名。
mimetypes
只检查文件名的结尾,它实际上不会根据文件内容进行猜测。mimetypes使用突出文件名来猜测类型。要从原始文件中检测文件类型,需要使用“magic”模块。python 3.8现在为此添加了一个更具体的错误,称为
gzip.BadGzipFile
。此错误仍然继承自
OSError
。也可以在没有binascii的情况下执行:
test\u f.read(2)=b'\x1f\x8b'
>>> with gzip.open('README.md', 'rb') as f:
...     f.read()
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 276, in read
    return self._buffer.read(size)
  File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 463, in read
    if not self._read_gzip_header():
  File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 411, in _read_gzip_header
    raise OSError('Not a gzipped file (%r)' % magic)
OSError: Not a gzipped file (b'# ')
import pathlib

if '.gz' in pathlib.Path(filepath).suffixes:
   # some more inexpensive checks until confident we can attempt to decompress
   # ...
   try ...
     ...
   except OSError as e:
     ...