我有一个Python程序,它将把文本文件作为输入。但是,其中一些文件可能是gzip压缩的。
是否存在跨平台,可以从Python方式使用以确定文件是否压缩为gzip?
以下是可靠的还是一个普通的文本文件'偶然'看起来像gzip一样足以让我得到误报?
try:
gzip.GzipFile(filename, 'r')
# compressed
# ...
except:
# not compressed
# ...
答案 0 :(得分:36)
gzip压缩文件的magic number为1f 8b
。尽管对此进行测试不是100%可靠,但“普通文本文件”从这两个字节开始的可能性极小 - 在UTF-8中甚至不合法。
通常,gzip压缩文件的后缀为.gz
。除非你gzip(1)
,否则即使--force
本身也不会解压缩文件。您可以想象使用它,但您仍然需要处理可能的IOError(在任何情况下都必须这样做)。
您的方法存在的一个问题是,gzip.GzipFile()
如果您向其提供未压缩文件,则不会引发异常。只有稍后的read()
会。这意味着,您可能需要两次实现一些程序逻辑。难看。
答案 1 :(得分:7)
“是否存在跨平台,可以通过Python方式确定文件是否压缩为gzip?”
接受的答案让我获得了90%的非常可靠的解决方案(测试前两个字节是1f 8b
),但没有说明如何在Python中实际执行此操作。这是一种可能的方式:
import binascii
def is_gz_file(filepath):
with open(filepath, 'rb') as test_f:
return binascii.hexlify(test_f.read(2)) == b'1f8b'
答案 2 :(得分:2)
导入mimetypes模块。 它可以自动猜测您拥有哪种文件,以及它是否已压缩。
即
mimetypes.guess_type('blabla.txt.gz')
返回:
('text / plain','gzip')
答案 3 :(得分:2)
从python3.7开始,这有效
import gzip
with gzip.open(input_file, 'r') as fh:
try:
fh.read(1)
except OSError:
print('input_file is not a valid gzip file by OSError')
从python3.8开始,这也有效:
import gzip
with gzip.open(input_file, 'r') as fh:
try:
fh.read(1)
except gzip.BadGzipFile:
print('input_file is not a valid gzip file by BadGzipFile')
答案 4 :(得分:1)
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'# ')
可以将此方法与其他方法结合使用以增强信心,例如检查mimetype或在文件头中查找幻数(例如,请参阅其他答案)并检查扩展名。
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:
...
答案 5 :(得分:0)
在python3中看起来效果不好......
import mimetypes
filename = "./datasets/test"
def file_type(filename):
type = mimetypes.guess_type(filename)
return type
print(file_type(filename))
返回(无,无) 但是从unix命令“File”
:〜&GT;文件数据集/测试 数据集/测试:gzip压缩数据,是“iostat_collection”,来自Unix,最后修改时间:2015年1月29日07:09:34