[编辑:此问题仅适用于32位系统。如果您的计算机、操作系统和Python实现均为64位,则映射大型文件可靠且极其高效。]
我正在编写一个模块,其中包括对文件进行按位读取的功能。这些文件可能很大(数百GB),因此我编写了一个简单的类,让我可以像处理字符串一样处理文件,并隐藏所有的寻址和读取细节。
在编写我的包装类时,我不知道有 mmap 模块 这个工具。阅读 mmap 的文档后,我认为“太好了 - 这正是我需要的,我将去掉自己的代码并使用 mmap 代替。它可能更有效率,而且删除代码总是好事。”
问题是 mmap 不适用于大型文件!这对我来说非常令人惊讶,因为我认为这是应用最明显的场景之一。如果文件大小超过几个GB,那么就会出现“EnvironmentError: [Errno 12] Cannot allocate memory”的错误。这只发生在32位的 Python 构建中,所以似乎是已经耗尽地址空间了,但我找不到任何相关的文档。
我的代码只有:
f = open('somelargefile', 'rb')
map = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
所以我的问题是,我有什么明显的遗漏吗? 有没有一种方法可以使mmap在大文件上可移植工作,还是我应该回到我的天真的文件包装器?
更新:似乎有一种感觉,Python的mmap应该有与POSIX mmap相同的限制。为了更好地表达我的挫败感,这里有一个简单的类,它具有mmap部分功能。
import os
class Mmap(object):
def __init__(self, f):
"""Initialise with a file object."""
self.source = f
def __getitem__(self, key):
try:
# A slice
self.source.seek(key.start, os.SEEK_SET)
return self.source.read(key.stop - key.start)
except AttributeError:
# single element
self.source.seek(key, os.SEEK_SET)
return self.source.read(1)
它是只读的,没有任何复杂的功能,但我可以像使用mmap一样使用它:
map2 = Mmap(f)
print map2[0:10]
print map2[10000000000:10000000010]
除了文件大小没有限制外,问题并不太难。