当前位置: 首页 > 面试题库 >

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

暴才俊
2023-03-14
问题内容

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

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


问题答案:

从IEEE 1003.1:

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

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

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



 类似资料:
  • 本文向大家介绍Python文本处理之按行处理大文件的方法,包括了Python文本处理之按行处理大文件的方法的使用技巧和注意事项,需要的朋友参考一下 以行的形式读出一个文件最简单的方式是使用文件对象的readline()、readlines()和xreadlines()方法。 Python2.2+为这种频繁的操作提供了一个简化的语法——让文件对象自身在行上高效迭代(这种迭代是严格的向前的)。 为了读

  • 上周,我决定尝试Perl6,并开始重新实现我的一个程序。我不得不说,Perl6对于对象编程来说非常容易,这对我来说是Perl5非常痛苦的一个方面。 我的程序必须读取和存储大文件,如整个基因组(高达3 Gb或更多,见下面的例子1)或制表数据。 代码的第一个版本是通过逐行迭代以Perl5的方式制作的(“基因组.fa”。对于正确的执行时间,它非常慢且不可行。 所以经过一点RTFM之后,我改变了文件上的s

  • 问题内容: 我刚刚在python解释器上执行了以下程序: 现在,我已经看到了,但是正如链接所言,八进制的0在python中不再起作用(即在python3中不起作用)。但这是否意味着应该正确解释以0开头的数字的行为?是以base-2还是以正常base-10表示?既然不是这样,为什么python会那样表现呢?这是实施问题吗?还是语义问题? 问题答案: 我的猜测是,由于在python3.x中不再是八进制

  • 问题内容: 我有一个使用Forms Authentication以asp.netmvc编写的后端服务器。当用户未通过身份验证时,服务器将自动发送302重定向到“登录”操作并返回“登录”页面。 在客户端,我有一个项目列表。只有经过身份验证的用户才能访问此列表。在页面上,我有一个使用Ajax(jQuery的$ .ajax函数)刷新列表的按钮。 现在,我的问题是身份验证票证超时并且用户单击“刷新”按钮时

  • 问题内容: 我正在针对以下测试文档进行测试: 如果使用lxml.html解析文档,则可以使用xpath获得IMG: 但是,如果我将文档解析为XML并尝试获取IMG标签,则会得到空结果: 我可以直接导航到该元素: 但这当然无助于我处理任意文档。我还希望能够查询etree以获得直接识别该元素的xpath表达式,从技术上讲,我可以这样做: 但是,同样,该xpath显然对解析任意文档没有用。 显然,我在这

  • 问题内容: 我一直在使用openSUSE 11.2 x86_64上的大型稀疏文件。当我尝试mmap()1TB的稀疏文件时,它因ENOMEM而失败。我本以为64位地址空间足以映射到TB级,但似乎还不够。进一步试验,一个1GB的文件可以正常工作,但是一个2GB的文件(以及更大的文件)会失败。我猜想可能有一个需要调整的地方,但是广泛的搜索没有任何效果。 这是一些显示问题的示例代码-有什么线索吗? 问题答