# 18.9。 `mmap` - 内存映射文件支持

内存映射文件对象的行为像`bytearray`和像file objects。您可以在预期`bytearray`的大多数地方使用mmap对象；例如，您可以使用`re`模块搜索内存映射文件。您还可以通过执行`obj [index] = 97`更改单个字节，到切片：`obj [i1：i2] = b'...'`。您还可以从当前文件位置开始读取和写入数据，并通过文件将`seek()`写入不同位置。

内存映射文件由`mmap`构造函数创建，在Unix和Windows上是不同的。在任一情况下，您必须为打开以进行更新的文件提供文件描述器。如果要映射现有的Python文件对象，请使用`fileno()`方法为fileno参数获取正确的值。否则，您可以使用`os.open()`函数打开文件，该函数直接返回一个文件描述器（该文件在完成后仍然需要关闭）。

注意

如果要为可写，缓冲的文件创建内存映射，应首先`flush()`。这是必要的，以确保对缓冲区的本地修改实际上可用于映射。

对于Unix和Windows版本的构造函数，可以将访问指定为可选的关键字参数。访问接受以下三个值之一：`ACCESS_READ`，`ACCESS_WRITE`或`ACCESS_COPY`以指定只读，或写时复写存储器。访问可以在Unix和Windows上使用。如果未指定访问，则Windows mmap会返回直写映射。所有三种访问类型的初始内存值取自指定的文件。分配给`ACCESS_READ`内存映射引发`TypeError`异常。分配给`ACCESS_WRITE`内存映射会影响内存和基础文件。分配给`ACCESS_COPY`内存映射会影响内存，但不会更新基础文件。

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

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

  （Windows版本）从文件句柄fileno指定的文件中映射长度字节，并创建一个mmap对象。如果length大于文件的当前大小，则文件将扩展为包含长度字节。如果length为`0`，则映射的最大长度为文件的当前大小，除非文件为空。Windows引发异常（您不能创建空在Windows上映射）。

  标记名（如果指定）而不是`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 [，t10> ] ）

  （Unix版本）从文件描述器fileno指定的文件中映射长度字节，并返回一个mmap对象。如果length是`0`，则调用`mmap`时，映射的最大长度将是文件的当前大小。

  flags指定映射的性质。`MAP_PRIVATE`创建私有写入副本映射，因此对mmap对象的内容的更改将对此进程是专用的，`MAP_SHARED`创建与所有共享的映射其他进程映射文件的相同区域。默认值为`MAP_SHARED`。

  prot如果指定，给出所需的内存保护；两个最有用的值是`PROT_READ`和`PROT_WRITE`，用于指定可以读取或写入页面。prot默认为`PROT_READ | PROT_WRITE`。

  可以指定访问代替标志和prot作为可选的关键字参数。指定标志，prot和访问是错误的。有关如何使用此参数的信息，请参见上述访问的说明。

  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()

  `mmap`也可以用作`with`语句中的上下文管理器。：

      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开始的计数字节复制到目标索引dest。如果mmap是用`ACCESS_READ`创建的，那么对move的调用将引发一个`TypeError`异常。

  `read`([n])

    返回一个`bytes`，其中包含从当前文件位置开始的n个字节。如果省略参数，无或否定，将所有字节从当前文件位置返回到映射结束。文件位置更新为指向返回的字节。

    在版本3.3中更改：参数可以省略或无。

  `read_byte`()

    以当前文件位置为单位返回一个字节，并将文件位置前移1。

  `readline`()

    返回单个行，从当前文件位置开始，直到下一个换行符。

  `resize`(newsize)

    调整地图和底层文件（如果有）。如果使用`ACCESS_READ`或`ACCESS_COPY`创建mmap，则调整地图大小将引发`TypeError`异常。

  `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)

    将字节中的字节写入文件指针当前位置的存储器；文件位置更新为指向写入的字节之后。如果使用`ACCESS_READ`创建mmap，则写入它将引发`TypeError`异常。

    在版本3.5中已更改：可写入bytes-like object现已接受。

  `write_byte`(byte)

    将整数字节写入文件指针当前位置的内存中；文件位置提前`1`。如果使用`ACCESS_READ`创建mmap，则写入它将引发`TypeError`异常。