mmap --- 內存映射文件支持?
內存映射(mmap)文件對象的行為既像 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 分別指定只讀,直寫或寫時復制內存,或 ACCESS_DEFAULT 推遲到 prot 。 access 可以在 Unix 和 Windows 上使用。如果未指定 access,則 Windows mmap 返回直寫映射。 這三種訪問類型的初始內存值均取自指定的文件。 分配給 ACCESS_READ 內存映射會引發 TypeError 異常。分配給 ACCESS_WRITE 內存映射會影響內存和基礎文件。 分配給 ACCESS_COPY 內存映射會影響內存,但不會更新基礎文件。
在 3.7 版更改: 添加了 ACCESS_DEFAULT 常量。
要映射匿名內存,應將 -1 作為 fileno 和 length 一起傳遞。
-
class
mmap.mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset])? ( Windows 版本) 映射被文件句柄 fileno 指定的文件的 length 個字節,并創建一個 mmap 對象。如果 length 大于當前文件大小,則文件將擴展為包含 length 個字節。如果 length 為
0,則映射的最大長度為當前文件大小。如果文件為空, Windows 會引發異常(你無法在Windows上創建空映射)。如果 tagname 被指定且不是
None,則是為映射提供標簽名稱的字符串。 Windows 允許你對同一文件擁有許多不同的映射。如果指定現有標簽的名稱,則會打開該標簽,否則將創建該名稱的新標簽。如果省略此參數或設置為None,則創建的映射不帶名稱。避免使用 tag 參數將有助于使代碼在Unix和Windows之間可移植。offset 可以被指定為非負整數偏移量。 mmap 引用將相對于從文件開頭的偏移。 offset 默認為0。 offeset 必須是
ALLOCATIONGRANULARITY的倍數。
-
class
mmap.mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE|PROT_READ, access=ACCESS_DEFAULT[, offset]) (Unix 版本) 映射文件描述符 fileno 指定的文件的 length 個字節,并返回一個 mmap 對象。如果 length 為
0,則當調用mmap時,映射的最大長度將為文件的當前大小。flags 指明映射的性質。
MAP_PRIVATE會創建私有的寫入時拷貝映射,因此對 mmap 對象內容的修改將為該進程所私有,而MAP_SHARED會創建與其他映射同一文件區域的進程所共享的映射。 默認值為MAP_SHARED。如果指明了 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。要確保已創建內存映射的有效性,描述符 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()
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 版更改: 現在支持可寫的 字節類對象。
-
flush([offset[, size]])? 將對文件的內存副本的修改刷新至磁盤。 如果不使用此調用則無法保證在對象被銷毀前將修改寫回存儲。 如果指定了 offset 和 size,則只將對指定范圍內字節的修改刷新至磁盤;在其他情況下,映射的全部范圍都會被刷新。 offset 必須為
PAGESIZE或ALLOCATIONGRANULARITY的倍數。(Windows version) A nonzero value returned indicates success; zero indicates failure.
(Unix 版本) 返回零值以表示成功。 當調用失敗時將引發異常。
-
move(dest, src, count)? 將從偏移量 src 開始的 count 個字節拷貝到目標索引號 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或ACCESS_COPY,則改變映射大小將引發TypeError異常。
-
rfind(sub[, start[, end]])? 返回子序列 sub 在對象內被找到的最大索引號,使得 sub 被包含在 [start, end] 范圍中。 可選參數 start 和 end 會被解讀為切片表示法。 如果未找到則返回
-1。在 3.5 版更改: 現在支持可寫的 字節類對象。
-
seek(pos[, whence])? 設置文件的當前位置。 whence 參數為可選項并且默認為
os.SEEK_SET或0(絕對文件定位);其他值還有os.SEEK_CUR或1(相對當前位置查找) 和os.SEEK_END或2(相對文件末尾查找)。
-
size()? 返回文件的長度,該數值可以大于內存映射區域的大小。
-
tell()? 返回文件指針的當前位置。
-
write(bytes)? 將 bytes 中的字節數據寫入文件指針當前位置的內存并返回寫入的字節總數 (一定不小于
len(bytes),因為如果寫入失敗,將會引發ValueError)。 在字節數據被寫入后文件位置將會更新。 如果 mmap 創建時設置了ACCESS_READ,則向其寫入將引發TypeError異常。在 3.5 版更改: 現在支持可寫的 字節類對象。
在 3.6 版更改: 現在會返回寫入的字節總數。
-
