mmap --- 內(nèi)存映射文件支持?
內(nèi)存映射(mmap)文件對象的行為既像 bytearray 又像 文件對象。 你可以在大部分接受 bytearray 的地方使用 mmap 對象;例如,你可以使用 re 模塊來搜索一個內(nèi)存映射文件。 你也可以通過執(zhí)行 obj[index] = 97 來修改單個字節(jié),或者通過對切片賦值來修改一個子序列: obj[i1:i2] = b'...'。 你還可以在文件的當前位置開始讀取和寫入數(shù)據(jù),并使用 seek() 前往另一個位置。
內(nèi)存映射文件是由 mmap 構(gòu)造函數(shù)創(chuàng)建的,其在 Unix和 Windows上是不同的。 無論哪種情況,你都必須為一個打開的文件提供文件描述符以進行更新。 如果你希望映射一個已有的 Python 文件對象,請使用該對象的 fileno() 方法來獲取 fileno 參數(shù)的正確值。 否則,你可以使用 os.open() 函數(shù)來打開這個文件,這會直接返回一個文件描述符(結(jié)束時仍然需要關閉該文件)。
注解
如果要為可寫的緩沖文件創(chuàng)建內(nèi)存映射,則應當首先 flush() 該文件。 這確保了對緩沖區(qū)的本地修改在內(nèi)存映射中可用。
對于 Unix 和 Windows版本的構(gòu)造函數(shù),可以將 access 指定為可選的關鍵字參數(shù)。 access 接受以下四個值之一: ACCESS_READ, ACCESS_WRITE 或 ACCESS_COPY 分別指定只讀,直寫或?qū)憰r復制內(nèi)存,或 ACCESS_DEFAULT 推遲到 prot 。 access 可以在 Unix 和 Windows 上使用。如果未指定 access,則 Windows mmap 返回直寫映射。 這三種訪問類型的初始內(nèi)存值均取自指定的文件。 分配給 ACCESS_READ 內(nèi)存映射會引發(fā) TypeError 異常。分配給 ACCESS_WRITE 內(nèi)存映射會影響內(nèi)存和基礎文件。 分配給 ACCESS_COPY 內(nèi)存映射會影響內(nèi)存,但不會更新基礎文件。
在 3.7 版更改: 添加了 ACCESS_DEFAULT 常量。
要映射匿名內(nèi)存,應將 -1 作為 fileno 和 length 一起傳遞。
-
class
mmap.mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset])? ( Windows 版本) 映射被文件句柄 fileno 指定的文件的 length 個字節(jié),并創(chuàng)建一個 mmap 對象。如果 length 大于當前文件大小,則文件將擴展為包含 length 個字節(jié)。如果 length 為
0,則映射的最大長度為當前文件大小。如果文件為空, Windows 會引發(fā)異常(你無法在Windows上創(chuàng)建空映射)。如果 tagname 被指定且不是
None,則是為映射提供標簽名稱的字符串。 Windows 允許你對同一文件擁有許多不同的映射。如果指定現(xiàn)有標簽的名稱,則會打開該標簽,否則將創(chuàng)建該名稱的新標簽。如果省略此參數(shù)或設置為None,則創(chuàng)建的映射不帶名稱。避免使用 tag 參數(shù)將有助于使代碼在Unix和Windows之間可移植。offset 可以被指定為非負整數(shù)偏移量。 mmap 引用將相對于從文件開頭的偏移。 offset 默認為0。 offeset 必須是
ALLOCATIONGRANULARITY的倍數(shù)。
-
class
mmap.mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE|PROT_READ, access=ACCESS_DEFAULT[, offset]) (Unix 版本) 映射文件描述符 fileno 指定的文件的 length 個字節(jié),并返回一個 mmap 對象。如果 length 為
0,則當調(diào)用mmap時,映射的最大長度將為文件的當前大小。flags 指明映射的性質(zhì)。
MAP_PRIVATE會創(chuàng)建私有的寫入時拷貝映射,因此對 mmap 對象內(nèi)容的修改將為該進程所私有,而MAP_SHARED會創(chuàng)建與其他映射同一文件區(qū)域的進程所共享的映射。 默認值為MAP_SHARED。如果指明了 prot,它將給出所需的內(nèi)存保護方式;最有用的兩個值是
PROT_READ和PROT_WRITE,分別指明頁面為可讀或可寫。 prot 默認為PROT_READ | PROT_WRITE。可以指定 access 作為替代 flags 和 prot 的可選關鍵字形參。 同時指定 flags, prot 和 access 將導致錯誤。 請參閱上文中 access 的描述了解有關如何使用此形參的信息。
offset 可以被指定為非負整數(shù)偏移量。 mmap 引用將相對于從文件開頭的偏移。 offset 默認為 0。 offset 必須是
ALLOCATIONGRANULARITY的倍數(shù),它在 Unix 系統(tǒng)上等價于PAGESIZE。要確保已創(chuàng)建內(nèi)存映射的有效性,描述符 fileno 所指定的文件在 Mac OS X 和 OpenVMS 上會與物理后備存儲進行內(nèi)部自動同步。
這個例子演示了使用
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 新版功能: 上下文管理器支持。
下面的例子演示了如何創(chuàng)建一個匿名映射并在父進程和子進程之間交換數(shù)據(jù)。:
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()
映射內(nèi)存的文件對象支持以下方法:
-
close()? 關閉 mmap。 后續(xù)調(diào)用該對象的其他方法將導致引發(fā) ValueError 異常。 此方法將不會關閉打開的文件。
-
closed? 如果文件已關閉則返回
True。3.2 新版功能.
-
find(sub[, start[, end]])? 返回子序列 sub 在對象內(nèi)被找到的最小索引號,使得 sub 被包含在 [start, end] 范圍中。 可選參數(shù) start 和 end 會被解讀為切片表示法。 如果未找到則返回
-1。在 3.5 版更改: 現(xiàn)在支持可寫的 字節(jié)類對象。
-
flush([offset[, size]])? 將對文件的內(nèi)存副本的修改刷新至磁盤。 如果不使用此調(diào)用則無法保證在對象被銷毀前將修改寫回存儲。 如果指定了 offset 和 size,則只將對指定范圍內(nèi)字節(jié)的修改刷新至磁盤;在其他情況下,映射的全部范圍都會被刷新。 offset 必須為
PAGESIZE或ALLOCATIONGRANULARITY的倍數(shù)。(Windows version) A nonzero value returned indicates success; zero indicates failure.
(Unix 版本) 返回零值以表示成功。 當調(diào)用失敗時將引發(fā)異常。
-
move(dest, src, count)? 將從偏移量 src 開始的 count 個字節(jié)拷貝到目標索引號 dest。 如果 mmap 創(chuàng)建時設置了
ACCESS_READ,則調(diào)用 move 將引發(fā)TypeError異常。
-
read([n])? 返回一個
bytes,其中包含從當前文件位置開始的至多 n 個字節(jié)。 如果參數(shù)省略,為None或負數(shù),則返回從當前文件位置開始直至映射結(jié)尾的所有字節(jié)。 文件位置會被更新為返回字節(jié)數(shù)據(jù)之后的位置。在 3.3 版更改: 參數(shù)可被省略或為
None。
-
read_byte()? 將當前文件位置上的一個字節(jié)以整數(shù)形式返回,并讓文件位置前進 1。
-
readline()? Returns a single line, starting at the current file position and up to the next newline.
-
resize(newsize)? 改變映射以及下層文件的大小,如果存在的話。 如果 mmap 創(chuàng)建時設置了
ACCESS_READ或ACCESS_COPY,則改變映射大小將引發(fā)TypeError異常。
-
rfind(sub[, start[, end]])? 返回子序列 sub 在對象內(nèi)被找到的最大索引號,使得 sub 被包含在 [start, end] 范圍中。 可選參數(shù) start 和 end 會被解讀為切片表示法。 如果未找到則返回
-1。在 3.5 版更改: 現(xiàn)在支持可寫的 字節(jié)類對象。
-
seek(pos[, whence])? 設置文件的當前位置。 whence 參數(shù)為可選項并且默認為
os.SEEK_SET或0(絕對文件定位);其他值還有os.SEEK_CUR或1(相對當前位置查找) 和os.SEEK_END或2(相對文件末尾查找)。
-
size()? 返回文件的長度,該數(shù)值可以大于內(nèi)存映射區(qū)域的大小。
-
tell()? 返回文件指針的當前位置。
-
write(bytes)? 將 bytes 中的字節(jié)數(shù)據(jù)寫入文件指針當前位置的內(nèi)存并返回寫入的字節(jié)總數(shù) (一定不小于
len(bytes),因為如果寫入失敗,將會引發(fā)ValueError)。 在字節(jié)數(shù)據(jù)被寫入后文件位置將會更新。 如果 mmap 創(chuàng)建時設置了ACCESS_READ,則向其寫入將引發(fā)TypeError異常。在 3.5 版更改: 現(xiàn)在支持可寫的 字節(jié)類對象。
在 3.6 版更改: 現(xiàn)在會返回寫入的字節(jié)總數(shù)。
-
