似乎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
答案 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()
<强>建议:强>
map
,这是一个内置函数。r+b
模式打开文件,如mmap
帮助页面上的Python示例所示。它声明:在任何一种情况下,您都必须为为更新而打开的文件提供文件描述符。见http://docs.python.org/library/mmap.html#mmap.mmap。UPPER_CASE_WITH_UNDERSCORES
全局变量名称,如https://www.python.org/dev/peps/pep-0008/#global-variable-names中全局变量名称中所述。在其他编程语言(如C)中,常量通常都是大写的。希望这有帮助。
编辑:我在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)
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