【问题标题】:Gzip output different after Python restartPython重启后Gzip输出不同
【发布时间】:2020-04-05 12:03:37
【问题描述】:

我正在尝试在 Python 3.6.8 中压缩一个 numpy 数组。

如果我运行这个 sn-p 两次(不同的解释器会话),我会得到不同的输出:

import gzip
import numpy
import base64

data = numpy.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0]])
compressed = base64.standard_b64encode(gzip.compress(data.data, compresslevel=9))
print(compressed.decode('ascii'))

示例结果(每次都不一样):

H4sIAPjHiV4C/2NgAIEP9gwQ4AChOKC0AJQWgdISUFoGSitAaSUorQKl1aC0BpTWgtI6UFoPShs4AABmfqWAgAAAAA==
H4sIAPrHiV4C/2NgAIEP9gwQ4AChOKC0AJQWgdISUFoGSitAaSUorQKl1aC0BpTWgtI6UFoPShs4AABmfqWAgAAAAA==
      ^

在循环中运行它(所以相同的解释器会话),每次都会给出相同的结果

for _ in range(1000):
    assert compressed == base64.standard_b64encode(gzip.compress(data.data, compresslevel=9))

我怎样才能每次都得到相同的结果? (最好没有外部库。)

【问题讨论】:

  • 为什么这对你很重要?
  • 将 mtime=0 参数添加到 gzip.compress(data.data, compresslevel=9) 时会发生什么?
  • @SinanKurmus 不存在,但如果我使用 mtime 创建自己的 BytesIO 和 GzipFile,那么它确实有效!你想把它变成答案吗?

标签: python gzip deterministic


【解决方案1】:

Gzip 在压缩时使用了一些文件信息(索引节点、时间戳等)(很好地讨论了 here)。您本身并没有使用文件,但您仍然在不同的时间使用它。所以这可能会产生影响(看看 Python 的 gzip 包装器实际上会提供更好的洞察力,但这超出了我的范围:)

因此,如果您有 Python 3.8+,请尝试在 gzip.compress(data.data, compresslevel=9) 中使用 mtime=0 参数,如

gzip.compress(data.data, compresslevel=9, mtime=0)

如果这不起作用(例如较旧的 Python 版本),那么您可以将 gzip.GzipFilemtime 参数一起使用,如下所示:

buf = io.BytesIO()
with GzipFile(fileobj=buf, mode='wb', compresslevel=compresslevel, mtime=0) as f:
    f.write(data)
result = buf.getvalue()

详细文档为here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2011-06-17
    • 1970-01-01
    • 2021-06-16
    • 2014-11-27
    • 1970-01-01
    相关资源
    最近更新 更多