为什么 Python zipfile 不提供与命令行 zip 相同的输出 .zip 文件大小?

Why does Python zipfile not give the same output .zip file size as command-line zip?

这里是zip生成的文件大小:

$ seq 10000 > 1.txt 
$ zip 1 1.txt
  adding: 1.txt (deflated 54%)
$ ls -og 1.zip 
-rw-r--r-- 1 22762 Aug 29 10:04 1.zip

这是一个等效的 python 脚本:

import zipfile
z = zipfile.ZipFile(sys.argv[1], 'w', zipfile.ZIP_DEFLATED)
fn = sys.argv[1]
z.writestr(zipfile.ZipInfo(fn), sys.stdin.read())
z.close()

生成的 zip 文件大小如下:

$ seq 10000 | ./main.py 2.zip 2.txt
$ ls -go 2.zip 
-rw-r--r-- 1 49002 Aug 29 10:15 2.zip

有人知道为什么 python 版本生成的 zip 文件没有 zip 生成的那么小吗?

事实证明(在python 3中检查)当使用ZipInfo时,writestr()不会使用compressioncompresslevel 14=]。这是一个糟糕的 API 设计示例。应该设计好是否使用ZipInfo,总是使用构造函数中的compressioncompresslevel

When passing a ZipInfo instance as the zinfo_or_arcname parameter, the compression method used will be that specified in the compress_type member of the given ZipInfo instance. By default, the ZipInfo constructor sets this member to ZIP_STORED.

正因如此,原来post上显示的python代码基本没有压缩。因此,python代码生成的文件较大。

此API设计的另一个问题是构造函数中的参数compression.writestr()compress_type相同,但它们的名称不同。这是另一个糟糕的设计。没有理由为同一个东西起不同的名字。