1. mmap記憶體映射檔案
建立一個檔案的記憶體映射將使用作業系統虛擬記憶體來直接訪問檔案系統上的資料,而不是使用常規的I/O函式訪問資料,記憶體映射通常可以提供I/O性能,因為使用記憶體映射是,不需要對每個訪問都建立一個單獨的系統呼叫,也不需要在緩沖區之間復制資料;實際上,內核和用戶應用都能直接訪問記憶體,
記憶體映射檔案可以看作是可修改的字串或類似檔案的物件,這取決于具體的需要,映射檔案支持一般的檔案API方法,如close()、flush()、read()、readline()、seek()、tell()和write(),它還支持字串API,提供分片等特性以及類似find()的方法,
下面的所有示例都會使用文本檔案lorem.txt,其中包含一些Lorem Ipsum,為便于參考,下面的代碼清單給出這個檔案的文本,
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla facilisi. Sed tristique eros eu libero. Pellentesque vel arcu. Vivamus purus orci, iaculis ac, suscipit sit amet, pulvinar eu, lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas dui. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam viverra fringilla leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet justo.
1.1 讀檔案
使用mmap()函式可以創建一個記憶體映射檔案,第一個引數是檔案描述符,可能來自file物件的fileno()方法,也可能來自os.open(),呼叫者在呼叫mmap()之前負責打開檔案,不再需要檔案時要負責將其關閉,
mmap()的第二個引數是要映射的檔案部分的大小(以位元組為單位),如果這個值為0,則映射整個檔案,如果這個大小大于檔案的當前大小,則會擴展該檔案,
這兩個平臺都支持一個可選的關鍵字引數access,使用ACCESS_READ表示只讀訪問;ACCESS_WRITE表示“寫通過”(write-through),即對記憶體的賦值直接寫入檔案;ACCESS_COPY表示“寫時復制”(copy-on-write),對記憶體的賦值不會寫至檔案,
import mmap with open('lorem.txt', 'r') as f: with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as m: print('First 10 bytes via read :', m.read(10)) print('First 10 bytes via slice:', m[:10]) print('2nd 10 bytes via read :', m.read(10))
檔案指標會跟蹤通過一個分片操作訪問的最后一個位元組,在這個例子中,第一次讀之后,指標向前移動10個位元組,然后由分片操作將指標重置回檔案的起點位置,并由分片使指標再次向前移動10個位元組,分片操作之后,再呼叫read()會給出檔案的11~20位元組,

1.2 寫檔案
要建立記憶體映射檔案來接收更新,映射之前首先要使用模式'r+'(而不是'w')打開檔案以便完成追加,然后可以使用任何改變資料的API方法(例如write()或賦值到一個分片等),
下面的例子使用了默認訪問模式ACCESS_WRITE,并賦值到一個分片,以原地修改某一行的一部分,
import mmap import shutil # Copy the example file shutil.copyfile('lorem.txt', 'lorem_copy.txt') word = b'consectetuer' reversed = word[::-1] print('Looking for :', word) print('Replacing with :', reversed) with open('lorem_copy.txt', 'r+') as f: with mmap.mmap(f.fileno(), 0) as m: print('Before:\n{}'.format(m.readline().rstrip())) m.seek(0) # rewind loc = m.find(word) m[loc:loc + len(word)] = reversed m.flush() m.seek(0) # rewind print('After :\n{}'.format(m.readline().rstrip())) f.seek(0) # rewind print('File :\n{}'.format(f.readline().rstrip()))
記憶體的檔案中第一行中間的單詞“consectetuer”將被替換,

使用訪問設定ACCESS_COPY時不會把修改寫入磁盤上的檔案,
import mmap import shutil # Copy the example file shutil.copyfile('lorem.txt', 'lorem_copy.txt') word = b'consectetuer' reversed = word[::-1] with open('lorem_copy.txt', 'r+') as f: with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_COPY) as m: print('Memory Before:\n{}'.format( m.readline().rstrip())) print('File Before :\n{}\n'.format( f.readline().rstrip())) m.seek(0) # rewind loc = m.find(word) m[loc:loc + len(word)] = reversed m.seek(0) # rewind print('Memory After :\n{}'.format( m.readline().rstrip())) f.seek(0) print('File After :\n{}'.format( f.readline().rstrip()))
在這個例子中,必須單獨的回轉檔案句柄和mmap句柄,因為這兩個物件的內部狀態會單獨維護,

1.3 正則運算式
由于記憶體映射檔案就類似于一個字串,因此也常與其他處理字串的模塊一起使用,如正則運算式,下面的例子會找出所有包含“nulla”的句子,
import mmap import re pattern = re.compile(rb'(\.\W+)?([^.]?nulla[^.]*?\.)', re.DOTALL | re.IGNORECASE | re.MULTILINE) with open('lorem.txt', 'r') as f: with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as m: for match in pattern.findall(m): print(match[1].replace(b'\n', b' '))
由于這個模式包含兩個組,所以findall()的回傳值是一個元組序列,print陳述句會找到匹配的句子,并用空格代替換行符,使各個結果都列印在同一行上,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/170790.html
標籤:Python
下一篇:PYTHON資料型別(基礎)
