18.9. mmap
—内存映射文件支持¶
内存映射文件对象的行为像 bytearray
和像 文件对象。你可以在大多数需要 bytearray
的地方使用mmap对象;例如,您可以使用 re
模块搜索内存映射文件。您也可以通过执行 obj[index] = 97
更改单个字节,或通过分配到切片来更改子序列:obj[i1:i2] = b'...'
。您还可以从当前文件位置开始读取和写入数据,并且 seek()
通过文件到不同位置。
内存映射文件由 mmap
构造函数创建,在Unix和Windows上是不同的。在任一情况下,您必须为打开以进行更新的文件提供文件描述符。如果要映射现有的Python文件对象,请使用其 fileno()
方法来获取 fileno 参数的正确值。否则,您可以使用 os.open()
函数打开文件,该函数直接返回文件描述符(完成后仍需要关闭该文件)。
注解
如果要为可写缓冲文件创建内存映射,则应首先 flush()
该文件。这是必要的,以确保对缓冲区的本地修改实际上可用于映射。
对于Unix和Windows版本的构造函数,access 可以指定为可选的关键字参数。 access 接受三个值之一:ACCESS_READ
,ACCESS_WRITE
或 ACCESS_COPY
,分别指定只读,直写或写时复制存储器。 access 可以在Unix和Windows上使用。如果未指定 access,则Windows mmap返回直写映射。所有三种访问类型的初始内存值取自指定的文件。分配到 ACCESS_READ
存储器映射会引发 TypeError
异常。分配给 ACCESS_WRITE
内存映射会影响内存和底层文件。 ACCESS_COPY
内存映射的分配会影响内存,但不会更新底层文件。
要映射匿名内存,-1应该作为fileno与长度一起传递。
-
class
mmap.
mmap
(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset])¶ (Windows版本) 从文件句柄 fileno 指定的文件中映射 length 字节,并创建一个mmap对象。如果 length 大于文件的当前大小,则文件扩展为包含 length 字节。如果 length 是
0
,则映射的最大长度是文件的当前大小,除非文件为空,Windows会引发异常(您不能在Windows上创建空映射)。tagname (如果指定而不是
None
)是给映射的标记名称的字符串。 Windows允许您对同一个文件有许多不同的映射。如果指定现有标记的名称,那么将打开该标记,否则将创建此名称的新标记。如果省略此参数或None
,则将创建没有名称的映射。避免使用tag参数将有助于在Unix和Windows之间移植代码。offset 可以被指定为非负整数偏移。 mmap引用将相对于从文件开头的偏移量。 offset 默认为0. offset 必须是ALLOCATIONGRANULARITY的倍数。
-
class
mmap.
mmap
(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE|PROT_READ, access=ACCESS_DEFAULT[, offset]) (Unix版本) 从文件描述符 fileno 指定的文件中映射 length 字节,并返回一个mmap对象。如果 length 是
0
,则当调用mmap
时,映射的最大长度将是文件的当前大小。flags 指定映射的性质。
MAP_PRIVATE
创建私有写时复制映射,因此对mmap对象的内容的更改对此过程是私有的,MAP_SHARED
创建与映射文件的相同区域的所有其他进程共享的映射。默认值为MAP_SHARED
。prot,如果指定,给出所需的存储器保护;两个最有用的值是
PROT_READ
和PROT_WRITE
,以指定可以读取或写入页面。 prot 默认为PROT_READ | PROT_WRITE
。可以指定 access 来代替 flags 和 prot 作为可选的关键字参数。指定 flags,prot 和 access 是错误的。有关如何使用此参数的信息,请参阅上述 access 的说明。
offset 可以被指定为非负整数偏移。 mmap引用将相对于从文件开头的偏移量。 offset 默认为0. offset 必须是PAGESIZE或ALLOCATIONGRANULARITY的倍数。
为了确保创建的内存映射的有效性,由描述符 fileno 指定的文件在内部自动与Mac OS X和OpenVMS上的物理后备存储同步。
此示例显示了使用
mmap
的一种简单方法:import mmap # write a simple example file with open("hello.txt", "wb") as f: f.write(b"Hello Python!\n") with open("hello.txt", "r+b") as f: # memory-map the file, size 0 means whole file mm = mmap.mmap(f.fileno(), 0) # read content via standard file methods print(mm.readline()) # prints b"Hello Python!\n" # read content via slice notation print(mm[:5]) # prints b"Hello" # update content using slice notation; # note that new content must have same size mm[6:] = b" world!\n" # ... and read again using standard file methods mm.seek(0) print(mm.readline()) # prints b"Hello world!\n" # close the map mm.close()
import mmap with mmap.mmap(-1, 13) as mm: mm.write(b"Hello world!")
3.2 新版功能: 上下文管理器支持。
下一个示例演示如何创建匿名地图并在父进程和子进程之间交换数据:
import mmap import os mm = mmap.mmap(-1, 13) mm.write(b"Hello world!") pid = os.fork() if pid == 0: # In a child process mm.seek(0) print(mm.readline()) mm.close()
内存映射文件对象支持以下方法:
-
close
()¶ 关闭mmap。对对象的其他方法的后续调用将导致产生ValueError异常。这将不会关闭打开的文件。
-
closed
¶ True
如果文件关闭。3.2 新版功能.
-
find
(sub[, start[, end]])¶ 返回找到子序列 sub 的对象中的最低索引,使得 sub 包含在范围[start,end]中。可选参数 start 和 end 解释为切片表示法。失败时返回
-1
。在 3.5 版更改: 可写 bytes-like object 现已被接受。
-
flush
([offset[, size]])¶ 将对文件的内存中副本所做的更改刷新回磁盘。不使用此调用,不能保证在对象被销毁之前写回更改。如果指定了 offset 和 size,则只将对给定字节范围的更改刷新到磁盘;否则,映射的整个范围被刷新。
(Windows版本) 返回非零值表示成功;零表示失败。
(Unix版本) 返回零值以指示成功。调用失败时引发异常。
-
move
(dest, src, count)¶ 将从偏移 src 开始的 count 字节复制到目标索引 dest。如果mmap是用
ACCESS_READ
创建的,那么调用move会引发一个TypeError
异常。
-
read
([n])¶ 返回从当前文件位置开始包含最多 n 个字节的
bytes
。如果省略参数None
或负数,则将所有字节从当前文件位置返回到映射结束。文件位置更新为指向返回的字节之后。在 3.3 版更改: 参数可以省略或
None
。
-
read_byte
()¶ 以当前文件位置作为整数返回一个字节,并将文件位置前移1。
-
readline
()¶ 返回单个行,从当前文件位置开始,直到下一个换行符。
-
rfind
(sub[, start[, end]])¶ 返回找到子序列 sub 的对象中的最高索引,使得 sub 包含在范围[start,end]中。可选参数 start 和 end 解释为切片表示法。失败时返回
-1
。在 3.5 版更改: 可写 bytes-like object 现已被接受。
-
seek
(pos[, whence])¶ 设置文件的当前位置。 whence 参数是可选的,默认为
os.SEEK_SET
或0
(绝对文件定位);其他值是os.SEEK_CUR
或1
(相对于当前位置寻找)和os.SEEK_END
或2
(相对于文件结尾寻找)。
-
size
()¶ 返回文件的长度,可以大于内存映射区域的大小。
-
tell
()¶ 返回文件指针的当前位置。
-
write
(bytes)¶ 将 bytes 中的字节写入到文件指针的当前位置的存储器中,并返回写入的字节数(从不小于
len(bytes)
,因为如果写入失败,则会引发ValueError
)。文件位置更新为指向写入的字节。如果mmap是用ACCESS_READ
创建的,那么写入它将引发TypeError
异常。在 3.5 版更改: 可写 bytes-like object 现已被接受。
在 3.6 版更改: 现在返回写入的字节数。
-