Python gzip.open .tell()具有线性增加因子,使其变慢

时间:2014-11-19 09:34:33

标签: python file-io gzip

使用Python 3.3.5,我有一个代码如下:

with gzip.open(fname, mode='rb') as fh:
    fh.seek(savedPos)
    for line in fh:
        # some work is done
        savedPos = fh.tell()

在每一行上完成的工作对系统来说已经非常沉重,所以我并不希望有很多人。但我扔进调试计数器并得到以下结果:

48 rows/sec
28 rows/sec
19 rows/sec
15 rows/sec
13 rows/sec
13 rows/sec
9 rows/sec
10 rows/sec
9 rows/sec
9 rows/sec
8 rows/sec
8 rows/sec
8 rows/sec
8 rows/sec
7 rows/sec
7 rows/sec
7 rows/sec
7 rows/sec
5 rows/sec
...

这告诉我一些事情已经关闭,所以我把fh.tell()放在调试计数器/计时器函数中,这样fh.tell()每秒只执行一次并得到一个稳定的 65行/秒

我是完全下架还是不应该非常快?或者这只是gzip的副作用?

我曾经手动存储文件位置,但由于文件结尾不同,编码问题等原因,它偶尔也会出错,所以我认为fh.tell()会更准确。

有没有其他选择,或者你可以加快fh.tell()的速度吗?

2 个答案:

答案 0 :(得分:3)

我使用zlib的经验(尽管使用它来自C而不是python,但我怀疑问题是相同的)是寻求是慢的。 zlib不会跟踪它在文件中的位置,所以如果你寻找它必须从头开始解压缩,以便计算它应该寻求的前进多少未压缩字节。

换句话说,顺序读取或写入很好。如果你必须寻求,那么你就是一个受伤的世界。

答案 1 :(得分:3)

我怀疑你可以期待fh.seek(...)表现良好。

gzip使用压缩算法,其中压缩事物的方式取决于它之前的数据的整个历史记录。因此,有一个有效的seek操作,您还必须恢复解码器的内部状态。

无论如何,这是seek方法的代码:(lines 435-442

   elif self.mode == READ:
        if offset < self.offset:
            # for negative seek, rewind and do positive seek
            self.rewind()
        count = offset - self.offset
        for i in xrange(count // 1024):
            self.read(1024)
        self.read(count % 1024)

所以通过执行read调用来执行搜索 - 即读取和解压缩数据,直到它处于正确的文件位置,如果你向后搜索,它只是从一开始就重新开始并向前读取文件。