mmap — 記憶體對映檔案支援


可用性:非 WASI。

此模組在 WebAssembly 上不起作用或不可用。有關更多資訊,請參閱 WebAssembly 平臺

記憶體對映檔案物件既像 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_READACCESS_WRITEACCESS_COPY,分別指定只讀、直寫或寫時複製記憶體,或者 ACCESS_DEFAULT 以 defer 到 protaccess 可以在 Unix 和 Windows 上使用。如果未指定 access,Windows mmap 將返回直寫對映。所有三種訪問型別的初始記憶體值均取自指定檔案。對 ACCESS_READ 記憶體對映的賦值會引發 TypeError 異常。對 ACCESS_WRITE 記憶體對映的賦值會影響記憶體和底層檔案。對 ACCESS_COPY 記憶體對映的賦值會影響記憶體,但不會更新底層檔案。

3.7 版本中修改: 添加了 ACCESS_DEFAULT 常量。

要對映匿名記憶體,應將 -1 作為檔案描述符和長度一起傳遞。

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

(Windows 版本)從檔案控制代碼 fileno 指定的檔案中對映 length 位元組,並建立一個 mmap 物件。如果 length 大於檔案的當前大小,檔案將擴充套件到包含 length 位元組。如果 length0,則對映的最大長度是檔案的當前大小,但如果檔案為空,Windows 將引發異常(你不能在 Windows 上建立空對映)。

tagname,如果指定且不為 None,則是一個字串,給出對映的標籤名稱。Windows 允許你對同一個檔案進行許多不同的對映。如果你指定現有標籤的名稱,則該標籤將被開啟,否則將建立一個此名稱的新標籤。如果此引數省略或為 None,則建立無名稱的對映。避免使用 tagname 引數將有助於使你的程式碼在 Unix 和 Windows 之間保持可移植性。

offset 可以指定為非負整數偏移量。mmap 引用將相對於檔案開頭的偏移量。offset 預設為 0。offset 必須是 ALLOCATIONGRANULARITY 的倍數。

引發一個 審計事件 mmap.__new__,引數為 filenolengthaccessoffset

class mmap.mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE | PROT_READ, access=ACCESS_DEFAULT, offset=0, *, trackfd=True)

(Unix 版本)從檔案描述符 fileno 指定的檔案中對映 length 位元組,並返回一個 mmap 物件。如果 length0,則在呼叫 mmap 時,對映的最大長度將是檔案的當前大小。

flags 指定對映的性質。MAP_PRIVATE 建立一個私有的寫時複製對映,因此對 mmap 物件內容的更改將對此程序私有;MAP_SHARED 建立一個與所有其他對映同一檔案區域的程序共享的對映。預設值是 MAP_SHARED。某些系統具有額外的可能標誌,完整列表在 MAP_* 常量 中指定。

prot(如果指定)給出所需的記憶體保護;兩個最有用的值是 PROT_READPROT_WRITE,用於指定頁面可以讀取或寫入。prot 預設為 PROT_READ | PROT_WRITE

access 可以代替 flagsprot 指定為可選關鍵字引數。同時指定 flagsprotaccess 是錯誤的。有關如何使用此引數的資訊,請參閱上面對 access 的描述。

offset 可以指定為非負整數偏移量。mmap 引用將相對於檔案開頭的偏移量。offset 預設為 0。offset 必須是 ALLOCATIONGRANULARITY 的倍數,在 Unix 系統上它等於 PAGESIZE

如果 trackfdFalse,則由 fileno 指定的檔案描述符將不會被複制,並且生成的 mmap 物件將不會與對映的底層檔案關聯。這意味著 size()resize() 方法將失敗。此模式有助於限制開啟的檔案描述符的數量。

為了確保建立的記憶體對映的有效性,在 macOS 上,由描述符 fileno 指定的檔案會在內部自動與物理備份儲存同步。

3.13 版本中修改: 添加了 trackfd 引數。

此示例展示了使用 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()

引發一個 審計事件 mmap.__new__,引數為 filenolengthaccessoffset

記憶體對映檔案物件支援以下方法

close()

關閉 mmap。後續呼叫物件的其他方法將引發 ValueError 異常。這不會關閉已開啟的檔案。

closed

如果檔案已關閉,則為 True

在 3.2 版本加入。

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

返回物件中找到子序列 sub 的最低索引,使得 sub 包含在範圍 [start, end] 內。可選引數 startend 的解釋與切片表示法相同。失敗時返回 -1

3.5 版本中修改: 現在接受可寫 bytes-like object

flush()
flush(offset, size, /)

將對檔案記憶體副本所做的更改重新整理回磁碟。如果不使用此呼叫,則不能保證在物件銷燬之前將更改寫回。如果指定了 offsetsize,則只有給定位元組範圍內的更改會被重新整理到磁碟;否則,整個對映範圍都會被重新整理。offset 必須是 PAGESIZEALLOCATIONGRANULARITY 的倍數。

返回 None 表示成功。呼叫失敗時會引發異常。

3.8 版本中修改: 以前,成功時返回非零值;在 Windows 下,錯誤時返回零。成功時返回零;在 Unix 下,錯誤時引發異常。

madvise(option[, start[, length]])

向核心傳送關於從 start 開始並延伸 length 位元組的記憶體區域的建議 optionoption 必須是系統上可用的 MADV_* 常量 之一。如果省略 startlength,則跨越整個對映。在某些系統(包括 Linux)上,start 必須是 PAGESIZE 的倍數。

可用性:具有 madvise() 系統呼叫的系統。

在 3.8 版本加入。

move(dest, src, count)

將從偏移量 src 開始的 count 位元組複製到目標索引 dest。如果 mmap 是使用 ACCESS_READ 建立的,則呼叫 move 將引發 TypeError 異常。

read([n])

返回一個 bytes 物件,其中包含從當前檔案位置開始的最多 n 個位元組。如果省略引數、為 None 或為負數,則返回從當前檔案位置到對映末尾的所有位元組。檔案位置將更新為返回位元組之後的位置。

3.3 版本中修改: 引數可以省略或為 None

read_byte()

將當前檔案位置的位元組作為整數返回,並將檔案位置前進 1。

readline()

返回一行,從當前檔案位置開始到下一個換行符。檔案位置將更新為返回位元組之後的位置。

resize(newsize)

調整對映和底層檔案(如果有)的大小。

調整使用 ACCESS_READACCESS_COPY 訪問許可權建立的對映的大小,將引發 TypeError 異常。調整使用 trackfd 設定為 False 建立的對映的大小,將引發 ValueError 異常。

在 Windows 上:如果存在針對同一命名檔案的其他對映,調整對映大小將引發 OSError。調整匿名對映(即針對頁面檔案)的大小將靜默建立一個新對映,並將原始資料複製到新大小的長度。

3.11 版本中修改: 在持有其他對映時,嘗試調整大小會正確失敗。允許在 Windows 上調整匿名對映的大小。

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

返回物件中找到子序列 sub 的最高索引,使得 sub 包含在範圍 [start, end] 內。可選引數 startend 的解釋與切片表示法相同。失敗時返回 -1

3.5 版本中修改: 現在接受可寫 bytes-like object

seek(pos[, whence])

設定檔案的當前位置。whence 引數是可選的,預設為 os.SEEK_SET0(絕對檔案定位);其他值是 os.SEEK_CUR1(相對於當前位置查詢)和 os.SEEK_END2(相對於檔案末尾查詢)。

3.13 版本中修改: 返回新的絕對位置而不是 None

seekable()

返回檔案是否支援查詢,返回值始終為 True

在 3.13 版本加入。

size()

返回檔案的長度,該長度可能大於記憶體對映區域的大小。

tell()

返回檔案指標的當前位置。

write(bytes)

bytes 中的位元組寫入記憶體中檔案指標的當前位置,並返回寫入的位元組數(從不小於 len(bytes),因為如果寫入失敗,將引發 ValueError)。檔案位置將更新為寫入位元組之後的位置。如果 mmap 是使用 ACCESS_READ 建立的,則寫入它將引發 TypeError 異常。

3.5 版本中修改: 現在接受可寫 bytes-like object

3.6 版本中修改: 現在返回寫入的位元組數。

write_byte(byte)

將整數 byte 寫入記憶體中檔案指標的當前位置;檔案位置前進 1。如果 mmap 是使用 ACCESS_READ 建立的,則寫入它將引發 TypeError 異常。

MADV_* 常量

mmap.MADV_NORMAL
mmap.MADV_RANDOM
mmap.MADV_SEQUENTIAL
mmap.MADV_WILLNEED
mmap.MADV_DONTNEED
mmap.MADV_REMOVE
mmap.MADV_DONTFORK
mmap.MADV_DOFORK
mmap.MADV_HWPOISON
mmap.MADV_MERGEABLE
mmap.MADV_UNMERGEABLE
mmap.MADV_SOFT_OFFLINE
mmap.MADV_HUGEPAGE
mmap.MADV_NOHUGEPAGE
mmap.MADV_DONTDUMP
mmap.MADV_DODUMP
mmap.MADV_FREE
mmap.MADV_NOSYNC
mmap.MADV_AUTOSYNC
mmap.MADV_NOCORE
mmap.MADV_CORE
mmap.MADV_PROTECT
mmap.MADV_FREE_REUSABLE
mmap.MADV_FREE_REUSE

這些選項可以傳遞給 mmap.madvise()。並非每個選項都將在每個系統上存在。

可用性:具有 madvise() 系統呼叫的系統。

在 3.8 版本加入。

MAP_* 常量

mmap.MAP_SHARED
mmap.MAP_PRIVATE
mmap.MAP_32BIT
mmap.MAP_ALIGNED_SUPER
mmap.MAP_ANON
mmap.MAP_ANONYMOUS
mmap.MAP_CONCEAL
mmap.MAP_DENYWRITE
mmap.MAP_EXECUTABLE
mmap.MAP_HASSEMAPHORE
mmap.MAP_JIT
mmap.MAP_NOCACHE
mmap.MAP_NOEXTEND
mmap.MAP_NORESERVE
mmap.MAP_POPULATE
mmap.MAP_RESILIENT_CODESIGN
mmap.MAP_RESILIENT_MEDIA
mmap.MAP_STACK
mmap.MAP_TPRO
mmap.MAP_TRANSLATED_ALLOW_EXECUTE
mmap.MAP_UNIX03

這些是可以傳遞給 mmap.mmap() 的各種標誌。MAP_ALIGNED_SUPER 僅在 FreeBSD 上可用,MAP_CONCEAL 僅在 OpenBSD 上可用。請注意,某些選項可能在某些系統上不存在。

3.10 版本中修改: 添加了 MAP_POPULATE 常量。

3.11 版本新增: 添加了 MAP_STACK 常量。

3.12 版本新增: 添加了 MAP_ALIGNED_SUPERMAP_CONCEAL 常量。