《Python Cookbook 3rd》笔记(5.10):内存映射的二进制文件
內存映射的二進制文件
問題
你想內存映射一個二進制文件到一個可變字節數組中,目的可能是為了隨機訪問它的內容或者是原地做些修改。
解法
使用 mmap 模塊來內存映射文件。下面是一個工具函數,向你演示了如何打開一個文件并以一種便捷方式內存映射這個文件。
import os import mmap def memory_map(filename, access=mmap.ACCESS_WRITE):size = os.path.getsize(filename)fd = os.open(filename, os.O_RDWR)return mmap.mmap(fd, size, access=access)為了使用這個函數,你需要有一個已創建并且內容不為空的文件。下面是一個例子,教你怎樣初始創建一個文件并將其內容擴充到指定大小:
>>> size = 1000000 >>> with open('data', 'wb') as f: ... f.seek(size-1) ... f.write(b'\x00') ... >>>下面是一個利用 memory_map() 函數類內存映射文件內容的例子:
>>> m = memory_map('data') >>> len(m) 1000000 >>> m[0:10] b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' >>> m[0] 0 >>> # Reassign a slice >>> m[0:11] = b'Hello World' >>> m.close() >>> # Verify that changes were made >>> with open('data', 'rb') as f: ... print(f.read(11)) ... b'Hello World' >>>mmap() 返回的 mmap 對象同樣也可以作為一個上下文管理器來使用,這時候底層的文件會被自動關閉。比如:
>>> with memory_map('data') as m: ... print(len(m)) ... print(m[0:10]) ... 1000000 b'Hello World' >>> m.closed True >>>默認情況下, memeory_map() 函數打開的文件同時支持讀和寫操作。任何的修改內容都會復制回原來的文件中。如果需要只讀的訪問模式,可以給參數 access 賦值為mmap.ACCESS_READ 。比如:
m = memory_map(filename, mmap.ACCESS_READ)如果你想在本地修改數據,但是又不想將修改寫回到原始文件中,可以使用mmap.ACCESS_COPY :
m = memory_map(filename, mmap.ACCESS_COPY)討論
為了隨機訪問文件的內容,使用 mmap 將文件映射到內存中是一個高效和優雅的方法。例如,你無需打開一個文件并執行大量的 seek() , read() , write() 調用,只需要簡單的映射文件并使用切片操作訪問數據即可。
一般來講, mmap() 所暴露的內存看上去就是一個二進制數組對象。但是,你可以使用一個內存視圖來解析其中的數據。比如:
>>> m = memory_map('data') >>> # Memoryview of unsigned integers >>> v = memoryview(m).cast('I') >>> v[0] = 7 >>> m[0:4] b'\x07\x00\x00\x00' >>> m[0:4] = b'\x07\x01\x00\x00' >>> v[0] 263 >>>需要強調的一點是,內存映射一個文件并不會導致整個文件被讀取到內存中。也就是說,文件并沒有被復制到內存緩存或數組中。相反,操作系統僅僅為文件內容保留了一段虛擬內存。當你訪問文件的不同區域時,這些區域的內容才根據需要被讀取并映射到內存區域中。而那些從沒被訪問到的部分還是留在磁盤上。所有這些過程是透明的,在幕后完成!
如果多個 Python 解釋器內存映射同一個文件,得到的 mmap 對象能夠被用來在解釋器直接交換數據。也就是說,所有解釋器都能同時讀寫數據,并且其中一個解釋器所做的修改會自動呈現在其他解釋器中。很明顯,這里需要考慮同步的問題。但是這種方法有時候可以用來在管道或套接字間傳遞數據。
這一小節中函數盡量寫得很通用,同時適用于 Unix 和 Windows 平臺。要注意的是使用 mmap() 函數時會在底層有一些平臺的差異性。另外,還有一些選項可以用來創建匿名的內存映射區域。如果你對這個感興趣,確保你仔細研讀了Python 文檔中這方面的內容 。
總結
以上是生活随笔為你收集整理的《Python Cookbook 3rd》笔记(5.10):内存映射的二进制文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Python Cookbook 3rd
- 下一篇: 《Python Cookbook 3rd