Chr*_* B. 8 python gzip python-2.x bzip2
我正在查询数据库并使用Python归档结果,我正在尝试在将数据写入日志文件时压缩数据.不过,我遇到了一些问题.
我的代码看起来像这样:
log_file = codecs.open(archive_file, 'w', 'bz2')
for id, f1, f2, f3 in cursor:
log_file.write('%s %s %s %s\n' % (id, f1 or 'NULL', f2 or 'NULL', f3))
Run Code Online (Sandbox Code Playgroud)
但是,我的输出文件大小为1,409,780.bunzip2在文件上运行会生成一个大小为943,634的文件,并在其bzip2上运行会导致大小为217,275.换句话说,未压缩文件明显小于使用Python的bzip编解码器压缩的文件. 有没有办法解决这个问题,除了bzip2在命令行上运行?
我尝试了Python的gzip编解码器(将行更改为codecs.open(archive_file, 'a+', 'zip'))以查看它是否解决了问题.我仍然获得大文件,但是gzip: archive_file: not in gzip format当我尝试解压缩文件时也遇到错误. 那里发生了什么?
编辑:我原来在附加模式下打开文件,而不是写模式.虽然这可能是也可能不是问题,但如果文件以'w'模式打开,问题仍然存在.
正如其他发帖者所指出的,问题在于该codecs库不使用增量编码器来编码数据;而是使用增量编码器来编码数据。相反,它将馈送到该write方法的每个数据片段编码为压缩块。这是非常低效的,对于一个设计用于流的库来说,这是一个糟糕的设计决策。
讽刺的是,Python 中已经内置了一个完全合理的增量 bz2 编码器。创建一个自动执行正确操作的“类似文件”类并不困难。
import bz2
class BZ2StreamEncoder(object):
def __init__(self, filename, mode):
self.log_file = open(filename, mode)
self.encoder = bz2.BZ2Compressor()
def write(self, data):
self.log_file.write(self.encoder.compress(data))
def flush(self):
self.log_file.write(self.encoder.flush())
self.log_file.flush()
def close(self):
self.flush()
self.log_file.close()
log_file = BZ2StreamEncoder(archive_file, 'ab')
Run Code Online (Sandbox Code Playgroud)
需要注意的是:在本例中,我以追加模式打开了文件;将多个压缩流附加到单个文件与 完美配合bunzip2,但 Python 本身无法处理它(尽管有一个补丁)。如果您需要将创建的压缩文件读回 Python,请坚持每个文件一个流。