mmap --- 內存映射文件支持?


內存映射文件對象的行為既像 bytearray 又像 文件對象。 你可以在大部分接受 bytearray 的地方使用 mmap 對象;例如,你可以使用 re 模塊來搜索一個內存映射文件。 你也可以通過執(zhí)行 obj[index] = 97 來修改單個字節(jié),或者通過對切片賦值來修改一個子序列: obj[i1:i2] = b'...'。 你還可以在文件的當前位置開始讀取和寫入數據,并使用 seek() 前往另一個位置。

內存映射文件是由 mmap 構造函數創(chuàng)建的,其在 Unix 和 Windows 上是不同的。 無論哪種情況,你都必須為一個打開的文件提供文件描述符以進行更新。 如果你希望映射一個已有的 Python 文件對象,請使用該對象的 fileno() 方法來獲取 fileno 參數的正確值。 否則,你可以使用 os.open() 函數來打開這個文件,這會直接返回一個文件描述符(結束時仍然需要關閉該文件)。

備注

如果要為可寫的緩沖文件創(chuàng)建內存映射,則應當首先 flush() 該文件。 這確保了對緩沖區(qū)的本地修改在內存映射中可用。

對于 Unix 和 Windows 版本的構造函數,可以將 access 指定為可選的關鍵字參數。 access 接受以下四個值之一: ACCESS_READ , ACCESS_WRITEACCESS_COPY 分別指定只讀,直寫或寫時復制內存,或 ACCESS_DEFAULT 推遲到 prot 。 access 可以在 Unix 和 Windows 上使用。如果未指定 access ,則 Windows mmap 返回直寫映射。這三種訪問類型的初始內存值均取自指定的文件。向 ACCESS_READ 內存映射賦值會引發(fā) 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 個字節(jié),并創(chuàng)建一個 mmap 對象。如果 length 大于當前文件大小,則文件將擴展為包含 length 個字節(jié)。如果 length0,則映射的最大長度為當前文件大小。如果文件為空, Windows 會引發(fā)異常(你無法在Windows上創(chuàng)建空映射)。

如果 tagname 被指定且不是 None ,則是為映射提供標簽名稱的字符串。 Windows 允許你對同一文件擁有許多不同的映射。如果指定現(xiàn)有標簽的名稱,則會打開該標簽,否則將創(chuàng)建該名稱的新標簽。如果省略此參數或設置為 None ,則創(chuàng)建的映射不帶名稱。避免使用 tag 參數將有助于使代碼在Unix和Windows之間可移植。

offset 可以被指定為非負整數偏移量。 mmap 引用將相對于從文件開頭的偏移。 offset 默認為0。 offeset 必須是 ALLOCATIONGRANULARITY 的倍數。

引發(fā)一個 審計事件 mmap.__new__ 附帶參數 fileno, length, access, offset

class mmap.mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE|PROT_READ, access=ACCESS_DEFAULT[, offset])

(Unix 版本) 映射文件描述符 fileno 指定的文件的 length 個字節(jié),并返回一個 mmap 對象。如果 length0 ,則當調用 mmap 時,映射的最大長度將為文件的當前大小。

flags 指明映射的性質。 MAP_PRIVATE 會創(chuàng)建私有的寫入時拷貝映射,因此對 mmap 對象內容的修改將為該進程所私有。 而 MAP_SHARED 會創(chuàng)建與其他映射同一文件區(qū)域的進程所共享的映射。 默認值為 MAP_SHARED。 某些系統(tǒng)還具有額外的可用旗標,完整列表會在 MAP_* 常量 中指明。

如果指明了 prot,它將給出所需的內存保護方式;最有用的兩個值是 PROT_READPROT_WRITE,分別指明頁面為可讀或可寫。 prot 默認為 PROT_READ | PROT_WRITE。

可以指定 access 作為替代 flagsprot 的可選關鍵字形參。 同時指定 flags, protaccess 將導致錯誤。 請參閱上文中 access 的描述了解有關如何使用此形參的信息。

offset 可以被指定為非負整數偏移量。 mmap 引用將相對于從文件開頭的偏移。 offset 默認為 0。 offset 必須是 ALLOCATIONGRANULARITY 的倍數,它在 Unix 系統(tǒng)上等價于 PAGESIZE

To ensure validity of the created memory mapping the file specified by the descriptor fileno is internally automatically synchronized with physical backing store on macOS and 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()

mmap 也可以在 with 語句中被用作上下文管理器:

import mmap

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

3.2 新版功能: 上下文管理器支持。

下面的例子演示了如何創(chuàng)建一個匿名映射并在父進程和子進程之間交換數據。:

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()

引發(fā)一個 審計事件 mmap.__new__ 附帶參數 fileno, length, access, offset。

映射內存的文件對象支持以下方法:

close()?

關閉 mmap。 后續(xù)調用該對象的其他方法將導致引發(fā) ValueError 異常。 此方法將不會關閉打開的文件。

closed?

如果文件已關閉則返回 True。

3.2 新版功能.

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

返回子序列 sub 在對象內被找到的最小索引號,使得 sub 被包含在 [start, end] 范圍中。 可選參數 startend 會被解讀為切片表示法。 如果未找到則返回 -1。

在 3.5 版更改: 現(xiàn)在接受可寫的 字節(jié)類對象。

flush([offset[, size]])?

將對文件的內存副本的修改刷新至磁盤。 如果不使用此調用則無法保證在對象被銷毀前將修改寫回存儲。 如果指定了 offsetsize,則只將對指定范圍內字節(jié)的修改刷新至磁盤;在其他情況下,映射的全部范圍都會被刷新。 offset 必須為 PAGESIZEALLOCATIONGRANULARITY 的倍數。

返回 None 以表示成功。 當調用失敗時將引發(fā)異常。

在 3.8 版更改: 在之前版本中,成功時將返回非零值;在 Windows 下當發(fā)生錯誤時將返回零。 在 Unix 下 成功時將返回零值;當發(fā)生錯誤時將引發(fā)異常。

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

將有關內存區(qū)域的建議 option 發(fā)送至內核,從 start 開始擴展 length 個字節(jié)。 option 必須為系統(tǒng)中可用的 MADV_* 常量 之一。 如果省略 startlength,則會包含整個映射。 在某些系統(tǒng)中(包括 Linux),start 必須為 PAGESIZE 的倍數。

可用性: 具有 madvise() 系統(tǒng)調用的系統(tǒng)。

3.8 新版功能.

move(dest, src, count)?

將從偏移量 src 開始的 count 個字節(jié)拷貝到目標索引號 dest。 如果 mmap 創(chuàng)建時設置了 ACCESS_READ,則調用 move 將引發(fā) TypeError 異常。

read([n])?

返回一個 bytes,其中包含從當前文件位置開始的至多 n 個字節(jié)。 如果參數省略,為 None 或負數,則返回從當前文件位置開始直至映射結尾的所有字節(jié)。 文件位置會被更新為返回字節(jié)數據之后的位置。

在 3.3 版更改: 參數可被省略或為 None

read_byte()?

將當前文件位置上的一個字節(jié)以整數形式返回,并讓文件位置前進 1。

readline()?

返回一個單獨的行,從當前文件位置開始直到下一個換行符。 文件位置會被更新為返回字節(jié)數據之后的位置。

resize(newsize)?

改變映射以及下層文件的大小,如果存在的話。 如果 mmap 創(chuàng)建時設置了 ACCESS_READACCESS_COPY,則改變映射大小將引發(fā) TypeError 異常。

On Windows: Resizing the map will raise an OSError if there are other maps against the same named file. Resizing an anonymous map (ie against the pagefile) will silently create a new map with the original data copied over up to the length of the new size.

在 3.11 版更改: Correctly fails if attempting to resize when another map is held Allows resize against an anonymous map on Windows

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

返回子序列 sub 在對象內被找到的最大索引號,使得 sub 被包含在 [start, end] 范圍中。 可選參數 startend 會被解讀為切片表示法。 如果未找到則返回 -1。

在 3.5 版更改: 現(xiàn)在接受可寫的 字節(jié)類對象。

seek(pos[, whence])?

設置文件的當前位置。 whence 參數為可選項并且默認為 os.SEEK_SET0 (絕對文件定位);其他值還有 os.SEEK_CUR1 (相對當前位置查找) 和 os.SEEK_END2 (相對文件末尾查找)。

size()?

返回文件的長度,該數值可以大于內存映射區(qū)域的大小。

tell()?

返回文件指針的當前位置。

write(bytes)?

bytes 中的字節(jié)數據寫入文件指針當前位置的內存并返回寫入的字節(jié)總數 (一定不小于 len(bytes),因為如果寫入失敗,將會引發(fā) ValueError)。 在字節(jié)數據被寫入后文件位置將會更新。 如果 mmap 創(chuàng)建時設置了 ACCESS_READ,則向其寫入將引發(fā) TypeError 異常。

在 3.5 版更改: 現(xiàn)在接受可寫的 字節(jié)類對象。

在 3.6 版更改: 現(xiàn)在會返回寫入的字節(jié)總數。

write_byte(byte)?

將整數值 byte 寫入文件指針當前位置的內存;文件位置前進 1。 如果 mmap 創(chuàng)建時設置了 ACCESS_READ,則向其寫入將引發(fā) 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()。 不是每個選項都存在于每個系統(tǒng)中。

可用性: 具有 madvise() 系統(tǒng)調用的系統(tǒng)。

3.8 新版功能.

MAP_* 常量?

mmap.MAP_SHARED?
mmap.MAP_PRIVATE?
mmap.MAP_DENYWRITE?
mmap.MAP_EXECUTABLE?
mmap.MAP_ANON?
mmap.MAP_ANONYMOUS?
mmap.MAP_POPULATE?
mmap.MAP_STACK?

這些是可被傳給 mmap.mmap() 的各種旗標。 請注意某些選項在某些系統(tǒng)上可能不存在。

在 3.10 版更改: 增加了 MAP_POPULATE 常量。

3.11 新版功能: Added MAP_STACK constant.