从 Python 设置 gzip 时间戳

2024-03-30

我对使用 Python 压缩数据感兴趣gzip模块。碰巧我希望压缩输出是确定性的,因为这对于一般事物来说通常是一个非常方便的属性 - 如果某些不支持 gzip 的进程要寻找输出中的更改,或者如果输出将被加密签名。

不幸的是,每次的输出都不同。据我所知,唯一的原因是 gzip 标头中的时间戳字段,Python 模块始终用当前时间填充该字段。我认为实际上不允许您拥有没有时间戳的 gzip 流,这太糟糕了。

无论如何,Python 的调用者似乎没有办法gzip模块提供底层数据的正确修改时间。 (实际上gzip程序似乎在可能的情况下使用输入文件的时间戳。)我想这是因为基本上唯一关心时间戳的是gunzip命令写入文件时 - 现在,我,因为我想要确定性输出。这是不是要求太过分了?

还有其他人遇到过这个问题吗?

最不可怕的方法是什么gzip来自 Python 的一些具有任意时间戳的数据?


是的,你没有任何漂亮的选择。时间是用 _write_gzip_header 中的这一行写入的:

write32u(self.fileobj, long(time.time()))

由于它们没有为您提供覆盖时间的方法,因此您可以执行以下操作之一:

  1. 从 GzipFile 派生一个类,然后复制_write_gzip_header函数到您的派生类中,但在这一行中具有不同的值。
  2. 导入 gzip 模块后,将新代码分配给其时间成员。您实际上将在 gzip 代码中提供时间名称的新定义,因此您可以更改 time.time() 的含义。
  3. 复制整个 gzip 模块,并将其命名为 my_stable_gzip,然后更改所需的行。
  4. 将 CStringIO 对象作为 fileobj 传入,并在 gzip 完成后修改字节流。
  5. 编写一个假文件对象,跟踪写入的字节,并将所有内容传递到真实文件,除了您自己编写的时间戳字节。

这是选项#2 的示例(未经测试):

class FakeTime:
    def time(self):
        return 1225856967.109

import gzip
gzip.time = FakeTime()

# Now call gzip, it will think time doesn't change!

选项 #5 可能是最干净的,因为不依赖于 gzip 模块的内部(未经测试):

class GzipTimeFixingFile:
    def __init__(self, realfile):
        self.realfile = realfile
        self.pos = 0

    def write(self, bytes):
        if self.pos == 4 and len(bytes) == 4:
            self.realfile.write("XYZY")  # Fake time goes here.
        else:
            self.realfile.write(bytes)
        self.pos += len(bytes)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 Python 设置 gzip 时间戳 的相关文章

随机推荐