如何从mmapped文件中读取行?

时间:2011-11-16 12:27:10

标签: python file text mmap

似乎mmap界面只支持readline()。 如果我尝试迭代对象,我会得到字符而不是完整的行。

逐行读取mmap文件的“pythonic”方法是什么?

import sys
import mmap
import os


if (len(sys.argv) > 1):
  STAT_FILE=sys.argv[1]
  print STAT_FILE
else:
  print "Need to know <statistics file name path>"
  sys.exit(1)


with open(STAT_FILE, "r") as f:
  map = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
  for line in map:
    print line # RETURNS single characters instead of whole line

4 个答案:

答案 0 :(得分:28)

迭代mmap行的最简洁方法是

with open(STAT_FILE, "r+b") as f:
    map_file = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
    for line in iter(map_file.readline, b""):
        # whatever

请注意,在Python 3中,iter()的sentinel参数必须是bytes类型,而在Python 2中,它必须是str(即""而不是b"" {{1}})。

答案 1 :(得分:15)

我修改了你的例子:

with open(STAT_FILE, "r+b") as f:
        m=mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
        while True:
                line=m.readline()
                if line == '': break
                print line.rstrip()

<强>建议:

希望这有帮助。

编辑:我在Linux上进行了一些时序测试,因为评论让我好奇。以下是137MB文本文件上5次连续运行的时序比较。

正常文件访问:

real    2.410 2.414 2.428 2.478 2.490
sys     0.052 0.052 0.064 0.080 0.152
user    2.232 2.276 2.292 2.304 2.320

mmap文件访问权限:

real    1.885 1.899 1.925 1.940 1.954
sys     0.088 0.108 0.108 0.116 0.120
user    1.696 1.732 1.736 1.744 1.752

这些时间不包括print声明(我将其排除在外)。根据这些数字,我会说内存映射文件访问速度要快得多。

编辑2 :使用python -m cProfile test.py我收到了以下结果:

5432833    2.273    0.000    2.273    0.000 {method 'readline' of 'file' objects}
5432833    1.451    0.000    1.451    0.000 {method 'readline' of 'mmap.mmap' objects}

如果我没弄错,那么mmap要快得多。

此外,似乎not len(line)的表现比line == ''差,至少这是我解释探查器输出的方式。

答案 2 :(得分:1)

以下是相当简洁的:

with open(STAT_FILE, "r") as f:
    m = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
    while True:
        line = m.readline()  
        if line == "": break
        print line
    m.close()

请注意,line会保留换行符,因此您可能希望将其删除。这也是if line == ""做正确事情的原因(空行作为"\n"返回)。

原始迭代的工作原理是mmap尝试看起来像文件和字符串。它看起来像一个字符串,用于迭代。

我不知道为什么它不能(或选择不)提供readlines()/xreadlines()

答案 3 :(得分:0)

在Windows上,

Python 2.7 32bit在映射文件上的速度是两倍以上

在27MB,509k行的文本文件中(我的“ parse”功能并不有趣,它只是非常快速的readline()):

with open(someFile,"r") as f:
    if usemmap:
        m=mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    else:
        m=f
        e.parse(m)

使用MMAP:

read in 0.308000087738

没有MMAP:

read in 0.680999994278