小编典典

为什么Python的mmap无法处理大文件?

python

[编辑:此问题仅适用于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]

除了文件大小没有限制。真的不太难…


阅读 218

收藏
2020-12-20

共1个答案

小编典典

从IEEE 1003.1:

mmap()函数应在进程的地址空间与文件,共享内存对象或[TYM]类型的内存对象之间建立映射。

它需要所有的虚拟地址空间,因为这正是这样mmap() 做的

这是不是事实 真正 的内存不多了并不重要-你不能映射比你有更多的可用地址空间。由于您然后将结果当作存储器一样 进行
访问和访问,因此您建议如何精确地将2 ^
32多个字节访问到文件中?即使mmap()没有失败,您仍然只能读取前4GB,然后再用尽32位地址空间中的空间。当然,您可以mmap()在文件上滑动32位窗口,但这并不一定会为您带来任何好处,除非您可以优化访问方式以限制访问前一个窗口的次数。

2020-12-20