使用 Python 解压缩 .Z 文件

Uncompressing a .Z file with Python

我正在尝试使用 Python 解压缩 *.Z 文件。我通过 FTP(二进制模式)下载了它。该文件使用 7zip 成功解压缩(文件上的 "info" 表明其类型为 "Z")。原始文件可以在 ftp://cddis.gsfc.nasa.gov/gps/products/1860/igr18600.sp3.Z 找到。

我已经在 Python 中阅读了 zlib 模块的使用,并且有一些我正在使用的测试代码:

import zlib

comp_data = open('C:\Temp\igr18600.sp3.Z', 'rb').read()

print(comp_data[0:10])

uncomp_data = zlib.decompress(comp_data)
with open('c:\temp\igr18600.sp3', 'wb') as f:
    f.write(uncomp_data)
    f.close()

当我执行这个时,我得到以下输出:

b'\x1f\x9d\x90#\xc6@\x91\x01#F'
Traceback (most recent call last):
  File "test.py", line 7, in <module>
    uncomp_data = zlib.decompress(comp_data)
zlib.error: Error -3 while decompressing data: incorrect header check

zlib 显然不喜欢 header。前几个字节似乎与压缩文件的正确幻数序列 0x1F9d 匹配(根据 https://en.wikipedia.org/wiki/List_of_file_signatures)。

在紧要关头,我可以通过直接输出到 7zip 来解决这个问题。但我希望找到一个纯粹的 Python 类型的答案。尽管一天中的大部分时间都在谷歌上搜索答案(或此错误消息),但我运气不佳。也许我的搜索技能正在萎缩?

Python 在模块中没有等效的 Unix 解压缩功能,而这是解压缩 .Z 文件所需要的。您可能需要 a) shell 输出到 Unix 压缩命令,b) shell 输出到 gzip,c) shell 输出到 7-zip(gzip 和 7-zip 都有解压缩 .Z 文件的能力),d)修改 C 中的原始解压缩代码并将 link 修改为 Python(代码可在线获得),或 e)用原生 Python.

对于 d),您可以找到我编写的一些 C 代码来完成这项工作 in this answer on mathematica.stackexchange.com。请参阅 unlzw() 函数。

几年过去了,现在有 python 个软件包:unlzwunlzw3[1]

1) unlzw

  • GitHub:ionelmc/python-unlzw(最后一次提交 2017-10)
  • PyPI:unlzw
  • 文档:python-unlzw.readthedocs.io
  • Pros/Cons: 包提供了C-extension file (.so or .pyd) which makes it fast. The downside is that it has built versions only up to CPython 3.6 (as it is not maintained?),如果你在Windows上安装它,pip会下载.tar.gz,你会得到安装 C 编译器以使安装正常工作。我试过了,因为我安装了 C 编译器,所以它可以与 CPython 3.8.6 一起使用。

1.1) 安装*

pip install unlzw

*见上面 Pros/Cons 的注释。

1.2) 用法示例

from unlzw import unlzw

with open('file.Z', 'rb') as fh:
    compressed_data = fh.read()
    uncompressed_data = unlzw(compressed_data)

2) unlzw3

  • GitHub: scivision/unlzw3 (Last commit 2020-07). Based on github.com/umeat/unlzw
  • PyPI:unlzw3
  • Pros/Cons:纯 python 实现,这意味着它将在“任何”带有 python 的平台上安装 & 运行,包括没有 C 的 Windows -编译器。它也比 C 实现慢(参见下面的基准测试)。

2.1) 安装

pip install unlzw3

2.2) 用法示例

来自documentation:

import unlzw3
from pathlib import Path

uncompressed_data = unlzw3.unlzw(Path('file.Z'))

附录:基准测试

使用从 https://cddis.nasa.gov/archive/gnss/products/ionex/2020/145/ 下载的文件 igsg1450.20i.Z

unlzw
3.5 ms ± 93 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

unlzw3
166 ms ± 2.7 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

基准显示,对于 1000 个类似的 .Z 文件,使用 unlzw 只需等待 3.5 秒,而使用 unlzw3 则需要等待 2.8 分钟。对于一次性转换,差异可能无关紧要。


[1]其实都是基于Mark Adler's answer上mathematica.stackexchange.com