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_READACCESS_WRITEACCESS_COPY 分別用於指定唯讀、直寫 (write-through) 或寫入時複製 (copy-on-write) 記憶體,或ACCESS_DEFAULT 以遵從protaccess 在 Unix 和 Windows 上都可以使用。如果未指定access,Windows 的 mmap 會回傳直寫對映。三種存取類型的初始記憶體值都是取自指定的檔案。對ACCESS_READ 記憶體對映進行賦值會引發TypeError 例外。對ACCESS_WRITE 記憶體對映進行賦值會同時影響記憶體和底層檔案。對ACCESS_COPY 記憶體對映進行賦值會影響記憶體,但不會改變底層檔案。

在 3.7 版的變更:新增ACCESS_DEFAULT 常數。

要對映匿名記憶體,應將 -1 與長度一起作為 fileno 傳入。

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

(Windows 版本) 從檔案控制代碼 (file handle)fileno 指定的檔案來對映length 個位元組,並建立一個 mmap 物件。如果length 大於檔案目前的大小,檔案會被擴充為能夠包含length 個位元組。如果length0,對映的最大長度就是檔案目前的大小,但如果檔案為空,Windows 會引發例外(因無法在 Windows 上建立空白的對映)。

若有指定tagname 且不為None,則其為給定對映的標籤名稱字串。Windows 允許你對同一個檔案設定許多不同的對映。如果你指定了一個現有標籤名稱,該標籤就會被開啟,否則會建立一個具有此名稱的新標籤。如果省略此參數或為None,對映會在沒有名稱的情況下建立。避免使用tagname 參數將有助於保持你的程式碼在 Unix 和 Windows 之間的可移植性。

offset 可以指定為非負整數偏移量。mmap 的參照會是相對於從檔案開頭算起之偏移量。offset 預設為 0。offset 必須是ALLOCATIONGRANULARITY 的倍數。

引發一個附帶引數filenolengthaccessoffset稽核事件mmap.__new__

classmmap.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 的簡單方式:

importmmap# 寫入一個簡單的範例檔案withopen("hello.txt","wb")asf:f.write(b"Hello Python!\n")withopen("hello.txt","r+b")asf:# 對映檔案到記憶體,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()

mmap 也可以在with 陳述式中作為情境管理器使用:

importmmapwithmmap.mmap(-1,13)asmm:mm.write(b"Hello world!")

在 3.2 版被加入:情境管理器的支援。

下一個範例展示了如何建立匿名對映並在父行程與子行程之間交換資料:

importmmapimportosmm=mmap.mmap(-1,13)mm.write(b"Hello world!")pid=os.fork()ifpid==0:# 在子行程中mm.seek(0)print(mm.readline())mm.close()

引發一個附帶引數filenolengthaccessoffset稽核事件mmap.__new__

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

close()

關閉 mmap。後續對物件其他方法的呼叫將導致 ValueError 例外被引發。這不會關閉已開啟的檔案。

closed

若檔案已關閉則回傳True

在 3.2 版被加入.

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

回傳物件中找到子序列sub 的最小索引,使得sub 包含在範圍 [start,end] 中。可選引數startend 的直譯方式與切片標記法相同。失敗時回傳-1

在 3.5 版的變更:現在接受可寫入的類位元組物件

flush()
flush(offset,size,/)

將對檔案之記憶體內副本 (in-memory copy) 所做的變更給排清 (flush) 回磁碟。若不使用此呼叫,則無法保證在物件被銷毀之前變更會被寫回。如果指定了offsetsize,則只有給定位元組範圍的變更會被排清到磁碟;否則會排清整個對映範圍。offset 必須是PAGESIZEALLOCATIONGRANULARITY 的倍數。

回傳None 表示成功。呼叫失敗時會引發例外。

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

向核心 (kernel) 發送關於從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])

回傳一個從目前檔案位置開始、包含最多n 個位元組的bytes。如果引數被省略、為None 或為負數,則回傳從目前檔案位置到對映結尾的所有位元組。檔案位置會被更新為指向回傳的位元組之後。

在 3.3 版的變更:引數可以省略或為None

read_byte()

以整數形式回傳目前檔案位置的位元組,並將檔案位置前進 1。

readline()

回傳從目前檔案位置開始到下一個換行符號的單一行。檔案位置會被更新為指向回傳的位元組之後。

resize(newsize)

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

調整以accessACCESS_READACCESS_COPY 建立的對映大小會引發TypeError 例外。調整以trackfd 設定為False 建立的對映大小會引發ValueError 例外。

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

在 3.11 版的變更:當持有另一個對映時嘗試調整大小會正確失敗;在 Windows 上允許對匿名對映調整大小

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

回傳物件中找到子序列sub 的最大索引,使得sub 包含在範圍 [start,end] 中。可選引數startend 的直譯方式與切片標記法相同。失敗時回傳-1

在 3.5 版的變更:現在接受可寫入的類位元組物件

seek(pos[,whence])

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

在 3.13 版的變更:回傳新的絕對位置而非None

seekable()

回傳檔案是否支援定位 (seeking),回傳值永遠為True

在 3.13 版被加入.

size()

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

tell()

回傳檔案指標的目前位置。

write(bytes)

bytes 中的位元組寫入檔案指標目前位置的記憶體,並回傳寫入的位元組數(絕不會少於len(bytes),因為如果寫入失敗,會引發ValueError)。檔案位置會被更新為指向寫入的位元組之後。如果 mmap 是以ACCESS_READ 建立的,則對其寫入會引發TypeError 例外。

在 3.5 版的變更:現在接受可寫入的類位元組物件

在 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 常數。