mmap --- 記憶體對映檔案的支援¶
可用性: not WASI.
此模組在 WebAssembly 平台上不起作用或無法使用。更多資訊請參閱 WebAssembly 平台。
記憶體對映檔案物件 (memory-mapped file objects) 的行為類似於 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 分別用於指定唯讀、直寫 (write-through) 或寫入時複製 (copy-on-write) 記憶體,或 ACCESS_DEFAULT 以遵從 prot。access 在 Unix 和 Windows 上都可以使用。如果未指定 access,Windows 的 mmap 會回傳直寫對映。三種存取類型的初始記憶體值都是取自指定的檔案。對 ACCESS_READ 記憶體對映進行賦值會引發 TypeError 例外。對 ACCESS_WRITE 記憶體對映進行賦值會同時影響記憶體和底層檔案。對 ACCESS_COPY 記憶體對映進行賦值會影響記憶體,但不會改變底層檔案。
在 3.7 版的變更: 新增 ACCESS_DEFAULT 常數。
要對映匿名記憶體,應將 -1 與長度一起作為 fileno 傳入。
- class mmap.mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT, offset=0)¶
(Windows 版本) 從檔案控制代碼 (file handle) fileno 指定的檔案來對映 length 個位元組,並建立一個 mmap 物件。如果 length 大於檔案目前的大小,檔案會被擴充為能夠包含 length 個位元組。如果 length 為
0,對映的最大長度就是檔案目前的大小,但如果檔案為空,Windows 會引發例外(因無法在 Windows 上建立空白的對映)。若有指定 tagname 且不為
None,則其為給定對映的標籤名稱字串。Windows 允許你對同一個檔案設定許多不同的對映。如果你指定了一個現有標籤名稱,該標籤就會被開啟,否則會建立一個具有此名稱的新標籤。如果省略此參數或為None,對映會在沒有名稱的情況下建立。避免使用 tagname 參數將有助於保持你的程式碼在 Unix 和 Windows 之間的可移植性。offset 可以指定為非負整數偏移量。mmap 的參照會是相對於從檔案開頭算起之偏移量。offset 預設為 0。offset 必須是
ALLOCATIONGRANULARITY的倍數。引發一個附帶引數
fileno、length、access、offset的稽核事件mmap.__new__。
- class mmap.mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE | PROT_READ, access=ACCESS_DEFAULT, offset=0, *, trackfd=True)
(Unix 版本) 從檔案描述器 fileno 指定的檔案對映 length 個位元組,並回傳一個 mmap 物件。如果 length 為
0,對映的最大長度將是呼叫mmap時檔案的目前大小。flags 指定對映的性質。
MAP_PRIVATE會建立私有的寫入時複製對映,因此對 mmap 物件內容的變更將僅限於此行程,而MAP_SHARED會建立與所有其他對映相同檔案區域之行程共享的對映。預設值為MAP_SHARED。某些系統有額外的可用旗標,完整列表請參閱 MAP_* 常數。prot 若有指定,則會給予所需的記憶體保護;最常用的兩個值是
PROT_READ和PROT_WRITE,用於指定分頁可以被讀取或寫入。prot 預設為PROT_READ | PROT_WRITE。access 可以作為可選的關鍵字參數來指定,以代替 flags 和 prot。同時指定 flags、prot 和 access 會產生錯誤。關於如何使用此參數的資訊,請參閱上面 access 的說明。
offset 可以指定為非負整數偏移量。mmap 的參照將相對於從檔案開頭算起的偏移量。offset 預設為 0。offset 必須是
ALLOCATIONGRANULARITY的倍數,且在 Unix 系統上等於PAGESIZE。如果 trackfd 為
False,由 fileno 指定的檔案描述器將不會被複製,且產生的mmap物件將不會與對映的底層檔案關聯。這意味著size()和resize()方法會失敗。此模式對於限制開啟的檔案描述器數量很有用。為了確保建立的記憶體對映有效,在 macOS 上由描述器 fileno 指定的檔案會在內部自動與實體備份儲存同步。
在 3.13 版的變更: 新增 trackfd 參數。
這個範例示範了使用
mmap的簡單方式:import mmap # 寫入一個簡單的範例檔案 with open("hello.txt", "wb") as f: f.write(b"Hello Python!\n") with open("hello.txt", "r+b") as f: # 對映檔案到記憶體,size 0 表示整個檔案 mm = mmap.mmap(f.fileno(), 0) # 透過標準檔案方法讀取內容 print(mm.readline()) # 印出 b"Hello Python!\n" # 透過切片標記法讀取內容 print(mm[:5]) # 印出 b"Hello" # 使用切片標記法更新內容; # 注意新內容必須有相同的大小 mm[6:] = b" world!\n" # ... 然後再次使用標準檔案方法讀取 mm.seek(0) print(mm.readline()) # 印出 b"Hello world!\n" # 關閉對映 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: # 在子行程中 mm.seek(0) print(mm.readline()) mm.close()
引發一個附帶引數
fileno、length、access、offset的稽核事件mmap.__new__。記憶體對映檔案物件支援以下方法:
- close()¶
關閉 mmap。後續對物件其他方法的呼叫將導致 ValueError 例外被引發。這不會關閉已開啟的檔案。
- closed¶
若檔案已關閉則回傳
True。在 3.2 版被加入.
- find(sub[, start[, end]])¶
回傳物件中找到子序列 sub 的最小索引,使得 sub 包含在範圍 [start, end] 中。可選引數 start 和 end 的直譯方式與切片標記法相同。失敗時回傳
-1。在 3.5 版的變更: 現在接受可寫入的類位元組物件。
- flush()¶
- flush(offset, size, /)
將對檔案之記憶體內副本 (in-memory copy) 所做的變更給排清 (flush) 回磁碟。若不使用此呼叫,則無法保證在物件被銷毀之前變更會被寫回。如果指定了 offset 和 size,則只有給定位元組範圍的變更會被排清到磁碟;否則會排清整個對映範圍。offset 必須是
PAGESIZE或ALLOCATIONGRANULARITY的倍數。回傳
None表示成功。呼叫失敗時會引發例外。在 3.8 版的變更: 以前在 Windows 上成功時會回傳非零值,錯誤時回傳零。在 Unix 上成功時回傳零值,錯誤時引發例外。
- madvise(option[, start[, length]])¶
向核心 (kernel) 發送關於從 start 開始並延伸 length 個位元組之記憶體區域的建議 option。option 必須是系統上可用的 MADV_* 常數 之一。如果省略 start 和 length,則會涵蓋整個對映。在某些系統(包括 Linux)上,start 必須是
PAGESIZE的倍數。可用性:具有
madvise()系統呼叫的系統。在 3.8 版被加入.
- move(dest, src, count)¶
將從偏移量 src 開始的 count 個位元組複製到目的地索引 dest。如果 mmap 是以
ACCESS_READ建立的,則對 move 的呼叫會引發TypeError例外。
- read([n])¶
回傳一個從目前檔案位置開始、包含最多 n 個位元組的
bytes。如果引數被省略、為None或為負數,則回傳從目前檔案位置到對映結尾的所有位元組。檔案位置會被更新為指向回傳的位元組之後。在 3.3 版的變更: 引數可以省略或為
None。
- read_byte()¶
以整數形式回傳目前檔案位置的位元組,並將檔案位置前進 1。
- readline()¶
回傳從目前檔案位置開始到下一個換行符號的單一行。檔案位置會被更新為指向回傳的位元組之後。
- resize(newsize