18.9. mmap — 内存映射文件支持


内存映射文件对象的行为像 bytearray 和像 文件对象 。可以在大多数地方使用 mmap 对象若 bytearray 被期望;例如,可以使用 re 模块搜索内存映射文件。还可以改变单个字节通过执行 obj[index] = 97 ,或通过赋值切片改变子序列: obj[i1:i2] = b'...' 。还可以从当前文件位置开始读写数据,及 seek() 透过文件到不同位置。

内存映射文件的创建通过 mmap 构造函数,这在 Unix 和 Windows 会有所不同。无论哪种情况,都必须为更新打开文件提供文件描述符。若希望映射现有 Python 文件对象,使用其 fileno() 方法以获取正确值对于 fileno 参数。否则,可以打开文件使用 os.open() 函数,直接返回文件描述符 (文件仍需关闭当完成时)。

注意

若想要为可写缓冲文件创建内存映射,应 flush() 文件首先。这是必要的,以确保本地修改缓冲实际可用于映射。

对于 Unix 和 Windows 版本的构造函数, access 可以被指定为可选关键词参数。 access accepts one of three values: ACCESS_READ , ACCESS_WRITE ,或 ACCESS_COPY to specify read-only, write-through or copy-on-write memory respectively. access 可以用于 Unix 和 Windows。若 access is not specified, Windows mmap returns a write-through mapping. The initial memory values for all three access types are taken from the specified file. Assignment to an ACCESS_READ 内存映射引发 TypeError 异常。赋值 ACCESS_WRITE 内存映射影响内存和底层文件。赋值 ACCESS_COPY 内存映射影响内存但不会更新底层文件。

要映射匿名内存,-1 应作为 fileno 同长度一起传递。

class mmap. mmap ( fileno , length , tagname=None , access=ACCESS_DEFAULT [ , offset ] )

(Windows 版本) 映射 length 字节从文件指定通过文件句柄 fileno ,并创建 mmap 对象。若 length > 文件的当前大小,将扩展文件以包含 length 字节。若 length is 0 ,映射的最大长度是文件的当前大小,除文件为空 Windows 引发异常外 (不可以在 Windows 创建空映射)。

tagname ,若指定且不是 None ,是给出映射标签名的字符串。Windows 允许同一文件拥有许多不同映射。若指定现有标签名,则打开该标签,否则将创建此名称的新标签。若此参数被省略或 None ,不采用名称创建映射。避免标签参数的使用将有助于在 Unix 和 Windows 之间保持代码可移植。

offset 可以指定为非负整数偏移。mmap 引用将相对文件开头偏移。 offset 默认为 0。 offset must be a multiple of the ALLOCATIONGRANULARITY.

class mmap. mmap ( fileno , length , flags=MAP_SHARED , prot=PROT_WRITE|PROT_READ , access=ACCESS_DEFAULT [ , offset ] )

(Unix 版本) 映射 length 字节从文件指定通过文件描述符 fileno ,并返回 mmap 对象。若 length is 0 ,映射的最大长度将是文件的当前大小当 mmap 被调用。

flags 指定映射的性质。 MAP_PRIVATE 创建私有的写时拷贝映射,因此对 mmap 对象内容的更改将是此进程私有的,和 MAP_SHARED 创建与映射文件相同区域所有其它进程共享的映射。默认值为 MAP_SHARED .

prot 若指定,给出期望内存保护;2 个最有用的值是 PROT_READ and PROT_WRITE ,以指定页面可以被读取或写入。 prot 默认为 PROT_READ | PROT_WRITE .

access 可以指定以代替 flags and prot 作为可选关键词参数。它是错误的同时指定 flags , prot and access 。见描述对于 access 上文对如何使用此参数的有关信息。

offset 可以指定为非负整数偏移。mmap 引用将相对文件开头偏移。 offset 默认为 0。 offset must be a multiple of the PAGESIZE or 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()
						

mmap 还可以用作上下文管理器在 with statement.:

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 and end 按切片表示法解释。返回 -1 当故障时。

3.5 版改变: 可写 像字节对象 现接受。

flush ( [ offset [ , size ] ] )

Flushes changes made to the in-memory copy of a file back to disk. Without use of this call there is no guarantee that changes are written back before the object is destroyed. If offset and size are specified, only changes to the given range of bytes will be flushed to disk; otherwise, the whole extent of the mapping is flushed.

(Windows 版本) A nonzero value returned indicates success; zero indicates failure.

(Unix 版本) A zero value is returned to indicate success. An exception is raised when the call failed.

move ( dest , src , count )

拷贝 count 字节开始于偏移 src 到目的地索引 dest 。若创建 mmap 采用 ACCESS_READ ,那么调用 move 将引发 TypeError 异常。

read ( [ n ] )

返回 bytes 包含直到 n 字节从当前文件位置开始。若自变量被省略, None 或负数,返回从当前文件位置到映射结束的所有字节。文件位置将更新到返回字节之后。

3.3 版改变: 自变量可以省略或 None .

read_byte ( )

以整数形式返回当前文件位置的字节,并将文件位置推进 1。

readline ( )

Returns a single line, starting at the current file position and up to the next newline.

resize ( newsize )

重置映射和底层文件的大小,若有的话。若 mmap 的创建是采用 ACCESS_READ or ACCESS_COPY ,重置映射大小将引发 TypeError 异常。

rfind ( sub [ , start [ , end ] ] )

返回对象的最高索引当子序列 sub 被发现,这种 sub 包含在范围 [ start , end ]。可选自变量 start and end 按切片表示法解释。返回 -1 当故障时。

3.5 版改变: 可写 像字节对象 现接受。

seek ( pos [ , whence ] )

设置文件的当前位置。 whence 自变量可选且默认为 os.SEEK_SET or 0 (绝对文件位置);其它值 os.SEEK_CUR or 1 (寻址相对于当前位置) 和 os.SEEK_END or 2 (寻址相对于文件末尾)。

size ( )

返回文件的长度,可以大于内存映射大小。

tell ( )

返回文件指针的当前位置。

write ( bytes )

Write the bytes in bytes into memory at the current position of the file pointer; the file position is updated to point after the bytes that were written. If the mmap was created with ACCESS_READ ,那么写入它会引发 TypeError 异常。

3.5 版改变: 可写 像字节对象 现接受。

write_byte ( byte )

写入整数 byte 进文件指针当前位置内存;文件位置推进 1 。若创建 mmap 采用 ACCESS_READ ,那么写入它会引发 TypeError 异常。