使用mmap对整个fi应用regex

2024-05-04 02:26:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试使用以下代码将正则表达式应用于整个文件(不仅仅是每行独立):

import mmap, re

ifile = open(ifilename)
data = mmap.mmap(ifile.fileno(), 0)
print data
mo = re.search('error: (.*)', data)
if mo:
    print "found error"

这是基于对问题How do I re.search or re.match on a whole file without reading it all into memory?的回答

但我得到了以下错误:

^{pr2}$

我怎样才能解决这个问题?在


在问题Match multiline regex in file object中,我发现读取整个文件的另一种可能是以下内容,而不是mmap对象:

data = open("data.txt").read()

有什么理由更喜欢mmap而不是简单的缓冲区/字符串?在


Tags: 文件代码importresearchdataerroropen
1条回答
网友
1楼 · 发布于 2024-05-04 02:26:26

你真的有两个问题要问。在

你的技术问题

如果升级到Python的更新版本,您所面临的问题很可能会得到解决,或者至少应该得到更好的回溯。mmap docs指定您需要打开一个文件以更新mmap-it,而您当前没有这样做。在

ifile = open(ifilename) # default is to open as read

应该是这样:

^{pr2}$

或者,如果您可以像您在评论中提到的那样更新到Python2.6

with open(ifilename, 'r+') as fi:
    # do stuff with open file

如果您没有在2.7上打开具有写权限的文件并尝试对其进行mmap,则会引发“Permission denied”异常。我怀疑错误没有在2.3中实现,所以现在允许您继续使用一个无效的mmap对象,当您尝试用regex搜索它时,这个对象会失败。在

mmap与open().read()

最后,你将能够(几乎)用这两种方法做同样的事情。re.search(pattern, mmap_or_long_string)将搜索内存映射文件或read()调用产生的长字符串。在

这两种方法的主要区别在于虚拟内存和实际内存消耗。 在内存映射文件中,文件保留在磁盘上(或在任何地方),您可以通过虚拟内存地址直接访问它。当您使用read()读取文件时,您将同时将整个文件放入(真实)内存中。在

为什么要这样或那样:

  1. 文件大小
    您可以映射的文件大小的最大限制是虚拟内存地址空间的大小,它由CPU(32位或64位)决定。分配的内存必须是连续的,因此如果操作系统找不到足够大的块来分配内存,那么可能会出现分配错误。另一方面,当使用read()时,您的限制是可用的物理内存。如果访问的文件大于可用内存,并且不能读取单个行,请考虑mmap。

  2. 进程间的文件共享
    如果要并行处理大文件的只读操作,则可以将其映射到内存中,以便在进程之间共享它,而不是每个进程读取整个文件的副本。

  3. 可读性/熟悉度
    与内存映射相比,更多的人熟悉简单的open()和{}函数。除非您有令人信服的理由使用mmap,否则从长期来看,坚持使用基本IO函数可能会更好地维护。

  4. 速度
    这个是洗的。很多论坛和帖子都喜欢谈论mmap的速度(因为一旦文件被映射,它会绕过一些系统调用),但是底层机制仍然是访问磁盘,而读取整个文件会将所有内容放入内存,并且只在处理文件的开始和结束时执行磁盘访问。如果您试图考虑缓存(硬盘和CPU)、内存分页和文件访问模式,那么会有无穷的复杂性。坚持使用久经考验的真实分析方法要容易得多。您将根据您的个别用例和文件的访问模式看到不同的结果,所以对这两种情况进行分析,看看哪一种更快。

其他资源

A good summary of the differences
PyMOTW
A good SO question
Wikipedia Virtual Memory article

相关问题 更多 >