python 使用 mmap 模塊通過內存映射文件實現高效文件操作。1. 創建或打開文件并獲取文件描述符;2. 使用 mmap.mmap() 函數將文件映射到進程的虛擬地址空間,參數包括 fileno(文件描述符)、Length(映射長度)和 access(訪問模式);3. 像操作字節數組一樣直接讀寫內容,支持索引、readline()、seek() 等方法;4. 完成后關閉 mmap 對象以釋放資源。內存映射的優勢在于避免內核與用戶空間的數據拷貝,提升 i/o 效率,簡化代碼結構,并支持多進程共享文件數據。但需注意同步問題、文件大小限制及平臺差異。相比傳統 read/write 系統調用,內存映射減少了上下文切換和數據復制次數,尤其適用于大型數據庫、日志處理、圖像處理等需要頻繁訪問大文件的場景。例如,結合正則表達式可高效統計大型文本文件中單詞出現的次數,且無需逐行讀取。
內存映射文件,簡單來說,就是把文件的一部分或者全部映射到進程的虛擬地址空間。這樣,你就可以像訪問內存一樣訪問文件,而不用像傳統的文件I/O那樣,需要read/write 系統調用。python 提供了 mmap 模塊來操作內存映射文件。
import mmap # 創建一個文件 (或者打開一個已存在的文件) with open("test.txt", "wb") as f: f.write(b"Hello, memory map!") # 打開文件,并創建一個內存映射 with open("test.txt", "rb+") as f: mm = mmap.mmap(f.fileno(), length=0, Access=mmap.ACCESS_WRITE) # 打印當前內容 print(mm.readline()) # 修改內容 mm[0:5] = b"World" # 回到起始位置 mm.seek(0) print(mm.readline()) # 關閉內存映射 mm.close()
Python 如何使用 mmap 模塊?
mmap 模塊的核心在于 mmap() 函數。它接受幾個關鍵參數:
立即學習“Python免費學習筆記(深入)”;
- fileno: 文件的文件描述符,可以通過 file.fileno() 獲取。
- length: 映射的長度,默認為 0,表示映射整個文件。
- access: 訪問模式,例如 mmap.ACCESS_READ (只讀), mmap.ACCESS_WRITE (讀寫), mmap.ACCESS_COPY (寫時復制)。
一旦創建了 mmap 對象,你就可以像操作字節數組一樣操作它。你可以使用索引來訪問和修改內容,也可以使用 readline(), seek(), tell() 等方法。
內存映射的優勢是什么?
- 效率: 避免了內核空間和用戶空間之間的數據拷貝,提高了 I/O 效率。特別是對于大文件,可以顯著減少系統調用的次數。
- 簡單: 可以像訪問內存一樣訪問文件,代碼更簡潔。
- 共享: 多個進程可以同時映射同一個文件,實現進程間通信。
當然,它也有缺點:
- 同步: 需要注意多進程訪問時的同步問題。
- 文件大小: 映射長度受到文件大小的限制。
- 平臺依賴: 不同操作系統對內存映射的實現可能有所差異。
內存映射與傳統文件 I/O 的區別?
傳統文件 I/O (例如 read()/write()) 需要進行系統調用,將數據從內核緩沖區復制到用戶空間緩沖區,反之亦然。這個過程涉及上下文切換,開銷比較大。
內存映射則直接將文件內容映射到進程的虛擬地址空間,避免了數據拷貝。進程可以直接訪問映射的內存區域,而不需要系統調用。
舉個例子,假設你要讀取一個 1GB 的文件。使用傳統 I/O,你可能需要多次調用 read(),每次讀取一小部分數據。而使用內存映射,你可以一次性將整個文件映射到內存,然后像訪問一個大數組一樣訪問它。
內存映射在哪些場景下特別有用?
- 大型數據庫: 數據庫系統經常使用內存映射來訪問數據文件,提高性能。
- 共享內存: 多個進程需要共享數據時,可以使用內存映射來實現。
- 日志處理: 快速讀取和分析大型日志文件。
- 圖像處理: 處理大型圖像文件,避免頻繁的 I/O 操作。
例如,你可以使用內存映射來快速統計一個大型文本文件中某個單詞出現的次數。
import mmap import re def count_word(filename, word): with open(filename, "r") as f: with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mm: count = 0 for match in re.finditer(word.encode('utf-8'), mm): count += 1 return count filename = "large_text_file.txt" word = "example" count = count_word(filename, word) print(f"The word '{word}' appears {count} times in {filename}")
這個例子展示了如何使用 mmap 和正則表達式來快速查找大型文件中的單詞。注意,我們需要將單詞編碼為字節串,因為 mmap 對象返回的是字節。