Выход Gzip отличается после Python перезапуска - PullRequest
2 голосов
/ 05 апреля 2020

Я пытаюсь сжать массив numpy в Python 3.6.8.

Если я запускаю этот фрагмент дважды (разные сеансы интерпретатора), я получаю другой вывод:

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==
      ^

Запуская его в al oop (то есть один и тот же сеанс интерпретатора), он каждый раз дает один и тот же результат

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

Как я могу получать один и тот же результат каждый раз? (Желательно без внешних библиотек.)

1 Ответ

3 голосов
/ 06 апреля 2020

Gzip использует некоторую информацию о файле (inode, timestamp и т. Д. c) при сжатии (хорошее обсуждение этого здесь ). Вы не используете файлы сами по себе, но вы делаете это в разное время. Так что это может иметь эффект (взгляд на оболочку gzip Python на самом деле даст лучшее понимание, но это не для меня :)

Поэтому попробуйте использовать параметр mtime=0 в gzip.compress(data.data, compresslevel=9), если вы иметь Python 3.8+, как

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

, и если это не работает (например, более старая версия Python), то вы можете использовать gzip.GzipFile с параметром mtime, например так:

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

Для получения подробной информации, документация здесь :

...