亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python中mmap模塊處理大文本的操作方法

 更新時間:2023年02月07日 10:18:09   作者:程序猿-張益達  
這篇文章主要介紹了Python中mmap模塊(處理大文本),將一個普通文件映射到內(nèi)存中,通常在需要對文件進行頻繁讀寫時使用,這樣用內(nèi)存映射讀寫取代I/O緩存讀寫,以獲得較高的性能,需要的朋友可以參考下

如果現(xiàn)在有一個需求,我們需要處理一個20G的大文件,我們會怎么處理呢?思考下,我們需要怎么實現(xiàn)這個功能。

我們可能會這么實現(xiàn):

def get_datas():
    source_text_path = "路徑"
    with open(source_text_path, 'rb') as f:
        data = f.readlines()
    yield data
if __name__ == '__main__':
    for e in get_datas():
        deal_data(e)  # 處理數(shù)據(jù)

這樣雖然能實現(xiàn),但是我們處理的時候需要消耗的資源和性能不是很友好,所以我們要優(yōu)化,也就是使用mmap模塊。

mmap是一種虛擬內(nèi)存映射文件的方法,即將一個文件或者其它對象映射到進程的地址空間,實現(xiàn)文件磁盤地址和進程虛擬地址空間中一段虛擬地址的一一映射關系。它省掉了內(nèi)核態(tài)和用戶態(tài)頁copy這個動作(兩態(tài)間copy),直接將用戶態(tài)的虛擬地址與內(nèi)核態(tài)空間進行映射,進程直接讀取內(nèi)核空間,速度提高了,內(nèi)存占用也少了。

簡單點來說,mmap函數(shù)實現(xiàn)的是內(nèi)存共享。內(nèi)存共享是兩個不同的進程共享內(nèi)存的意思:同一塊物理內(nèi)存被映射到兩個進程的各自的進程地址空間。這個物理內(nèi)存已經(jīng)被規(guī)定了大?。ù笮∫欢ㄒ葘嶋H寫入的東東大)以及名稱。當需要寫入時,找到內(nèi)存名稱,然后寫入內(nèi)存,等需要讀取時候, 首先要知道你要讀取多大(因為物理內(nèi)存比你要讀取的東西大,全部讀取的話會讀到一些“空”的東西),然后尋找對應名稱的物理塊,然后讀取。

mmap 介紹

Windows

mmap.mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset])

參數(shù)說明:

  • fileno:文件描述符,可以是file對象的fileno()方法,或者來自os.open(),在調(diào)用mmap()之前打開文件,不再需要文件時要關閉。

  • length:要映射文件部分的大?。ㄒ宰止?jié)為單位),這個值為0,則映射整個文件,如果大小大于文件當前大小,則擴展這個文件。

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

  • access:文件權限

  • ACCESS_READ:讀訪問;

  • ACCESS_WRITE:寫訪問,默認;

  • ACCESS_COPY:拷貝訪問,不會把更改寫入到文件,使用flush把更改寫到文件。

offset:非負整數(shù)偏移量,默認從0開始。

Unix

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

參數(shù)說明:

  • flags:映射的性質(zhì),默認MAP_SHARED。
  • MAP_PRIVATE 會創(chuàng)建私有的寫入時拷貝映射,因此對mmap對象內(nèi)容的修改將為該進程所私有;
  • MAP_SHARED 會創(chuàng)建與其他映射同一文件區(qū)域的進程所共享的映射。
  • prot:它將給出所需的內(nèi)存保護方式;最有用的兩個值是 PROT_READ和 PROT_WRITE,分別指明頁面為可讀或可寫。 prot 默認為PROT_READ | PROT_WRITE。
  • access:注意的是可以指定 access 作為替代 flags 和 prot 的可選關鍵字形參。 同時指定 flags,prot 和 access 將導致錯誤。

fileno文件描述符有如下

  • os.O_RDONLY:以只讀的方式打開Readonly
  • os.O_WRONLY:以只寫的方式打開Write only
  • os.O_RDWR:以讀寫的方式打開 Read and write
  • os.O_APPEND:以追加的方式打開
  • os.O_CREAT:創(chuàng)建并打開一個新文件
  • os.O_EXCL:os.O_CREAT| os.O_EXCL 如果指定的文件存在,返回錯誤
  • os.O_TRUNC:打開一個文件并截斷它的長度為零(必須有寫權限)
  • os.O_BINARY:以二進制模式打開文件(不轉換)
  • os.O_NOINHERIT:阻止創(chuàng)建一個共享的文件描述符
  • os.O_SHORT_LIVED
  • os.O_TEMPORARY:與O_CREAT一起創(chuàng)建臨時文件
  • os.O_RANDOM:緩存優(yōu)化,但不限制從磁盤中隨機存取
  • os.O_SEQUENTIAL :緩存優(yōu)化,但不限制從磁盤中序列存取
  • os.O_TEXT:以文本的模式打開文件(轉換)

支持的方法

  • close(): 關閉 mmap。 后續(xù)調(diào)用該對象的其他方法將導致引發(fā) ValueError 異常。 此方法將不會關閉打開的文件。
  • closed: 如果文件已關閉則返回 True。
  • find(str, start, end): 從 start 下標開始,在 m中從左往右尋找子串 str最早出現(xiàn)的下標;沒有找到則返回-1。
  • flush([offset, n]):將對文件的內(nèi)存副本的修改刷新至磁盤。 如果不使用此調(diào)用則無法保證在對象被銷毀前將修改寫回存儲。 如果指定了 offset和 size,則只將對指定范圍內(nèi)字節(jié)的修改刷新至磁盤;在其他情況下,映射的全部范圍都會被刷新。
  • windows: 返回的非零值表示成功;否則返回0。 零表示失敗。
  • unix: 返回零值以表示成功。 當調(diào)用失敗時將引發(fā)異常。
  • move(dest, src, count): 將從偏移量 src開始的 count個字節(jié)拷貝到目標索引號 dest。 如果 mmap 創(chuàng)建時設置了 ACCESS_READ,則調(diào)用 move將引發(fā)異常。
  • read([n]): 返回一個字節(jié),其中包含從當前文件位置開始的至多 n 個字節(jié)。 如果參數(shù)省略,為 None 或負數(shù),則返回從當前文件位置開始直至映射結尾的所有字節(jié)。 文件位置會被更新為返回字節(jié)數(shù)據(jù)之后的位置
  • read_byte():返回一個1字節(jié)長的字符串,從 m 對應的文件中讀1個字節(jié),要是已經(jīng)到了EOF還調(diào)用 read_byte(),則拋出異常 ValueError。
  • readline():返回一個字符串,從 m 對應文件的當前位置到下一個’\n’,當調(diào)用 readline() 時文件位于 EOF,則返回空字符串。
  • resize(newsize):如果存在的話, 改變映射以及下層文件的大小。 如果 mmap 創(chuàng)建時設置了 ACCESS_READ或 ACCESS_COPY,則改變映射大小將引發(fā)異常。
  • rfind(sub[, start[, end]]):返回子序列 sub在對象內(nèi)被找到的最大索引號,使得 sub 被包含在 [start, end] 范圍中。 可選參數(shù) start和 end 會被解讀為切片表示法。 如果未找到則返回 -1。
  • seek(pos[, whence]):設置文件的當前位置。 whence 參數(shù)為可選項并且默認為 os.SEEK_SET 或 0 (絕對文件定位);其他值還有 os.SEEK_CUR 或 1 (相對當前位置查找) 和 os.SEEK_END 或 2 (相對文件末尾查找)。
  • size():返回文件的長度,該數(shù)值可以大于內(nèi)存映射區(qū)域的大小。
  • tell():返回文件指針的當前位置。
  • write(str):將str寫入文件指針當前位置的內(nèi)存并返回寫入的字節(jié)總數(shù) (一定不小于 len(str),因為如果寫入失敗,將會引發(fā)錯誤)。 在字節(jié)數(shù)據(jù)被寫入后文件位置將會更新。 如果 mmap 創(chuàng)建時設置了 ACCESS_READ,則向其寫入將引發(fā) 異常
  • write_byte(byte):將整數(shù)值 byte 寫入文件指針當前位置的內(nèi)存;文件位置前進 1。 如果 mmap 創(chuàng)建時設置了 ACCESS_READ,則向其寫入將引發(fā)異常。

對于EOF的處理,write() 和 read_byte() 拋出異常 ValueError,而 write_byte() 和 read() 什么都不做。

使用mmap讀取大文件

from mmap import mmap
def read_data(file_path):
    with open(file_path, "r+") as f:
        m = mmap(f.fileno(), 0)
        g_index = 0
        for index, char in enumerate(m):
            if char == b"\n":
                yield m[g_index:index + 1].decode()
                g_index = index + 1
if __name__ == "__main__":
    file_path = ""
    for content in read_data(file_path):
        print(content)

什么時候用mmap?

用mmap來讀取超大文件,不是mmap的主要應用場景,Python官方文件也沒有提到這一點。如果僅僅是讀取超大文件,使用文件對象的read(N),來得更快更好更簡單。

關于標準庫中的mmap模塊。現(xiàn)有一個需求,要對超大文件(接近40G)進行讀寫,notepad++等工具直接拒絕打開此文件。用 r+ 模式打開文件,可以隨意讀寫,但是要特別小心。readline()是否能夠使用,要看這個文件每行都多長,如果沒有換行,就不能用,就算知道每行的大小,也要帶個參數(shù)N來控制最大讀取數(shù)量。readlines()是肯定不能用的,就算帶參數(shù),也可能直接卡死!read(N)沒問題,主要控制是N的大小。

總之,傳統(tǒng)讀寫文件的方式可以用,但是不夠方便。速度也是個問題,傳統(tǒng)的緩存IO方式,涉及到OS內(nèi)核態(tài)的內(nèi)存和進程虛擬空間內(nèi)存的內(nèi)容交換,對于超大文件而言,這種交換會浪費大量的CPU時間和內(nèi)存。mmap是另一個方式!它省掉了內(nèi)核態(tài)和用戶態(tài)頁拷貝這個動作(兩態(tài)間copy),直接將用戶態(tài)的虛擬地址與內(nèi)核態(tài)空間進行映射,進程直接讀取內(nèi)核空間,速度提高了,內(nèi)存占用也少了。

總結來說,常規(guī)文件操作為了提高讀寫效率和保護磁盤,使用了頁緩存機制。這樣造成讀文件時需要先將文件頁從磁盤拷貝到頁緩存中,由于頁緩存處在內(nèi)核空間,不能被用戶進程直接尋址,所以還需要將頁緩存中數(shù)據(jù)頁再次拷貝到內(nèi)存對應的用戶空間中。這樣,通過了兩次數(shù)據(jù)拷貝過程,才能完成進程對文件內(nèi)容的獲取任務。寫操作也是一樣,待寫入的buffer在內(nèi)核空間不能直接訪問,必須要先拷貝至內(nèi)核空間對應的主存,再寫回磁盤中(延遲寫回),也是需要兩次數(shù)據(jù)拷貝。

而使用mmap操作文件中,創(chuàng)建新的虛擬內(nèi)存區(qū)域和建立文件磁盤地址和虛擬內(nèi)存區(qū)域映射這兩步,沒有任何文件拷貝操作。而之后訪問數(shù)據(jù)時發(fā)現(xiàn)內(nèi)存中并無數(shù)據(jù)而發(fā)起的缺頁異常過程,可以通過已經(jīng)建立好的映射關系,只使用一次數(shù)據(jù)拷貝,就從磁盤中將數(shù)據(jù)傳入內(nèi)存的用戶空間中,供進程使用。

總而言之,常規(guī)文件操作需要從磁盤到頁緩存再到用戶主存的兩次數(shù)據(jù)拷貝。而mmap操控文件,只需要從磁盤到用戶主存的一次數(shù)據(jù)拷貝過程。說白了,mmap的關鍵點是實現(xiàn)了用戶空間和內(nèi)核空間的數(shù)據(jù)直接交互而省去了空間不同數(shù)據(jù)不通的繁瑣過程。因此在某些場景下,mmap效率更高。

從python官網(wǎng)上看mmap的介紹,生成的mmap對象,就像一個bytearray對象,可以直接用index的方式讀寫,可以切片。同時,mmap對象還有一組類似文件操作的接口,read,readline,flush等等。即mmap對象兼具bytearray和file對象的功能。不過還是要注意,對于超大文件的讀(先不考慮寫的問題吧),從磁盤到內(nèi)核,依然會占用內(nèi)存,因此絕對不能一口氣全部讀出來。read(N)是必須的,mmap的使用只是可能會提高效率。(如果頻繁的創(chuàng)建和關閉mmap映射,這種創(chuàng)建是為了指向超大文件的不同位置,反而效率更低。一般情況下的read(N)實現(xiàn),不需要使用mmap。)

mmap的另一個應用場景,是進程間的內(nèi)存共享。多個進程將同一個文件map到同一段內(nèi)核地址上,即實現(xiàn)了相互之間的共同訪問。

總結:使用mmap的時機

  • 將一個普通文件映射到內(nèi)存中,通常在需要對文件進行頻繁讀寫時使用,這樣用內(nèi)存映射讀寫取代I/O緩存讀寫,以獲得較高的性能;
  • 將特殊文件進行匿名內(nèi)存映射,可以為關聯(lián)進程提供共享內(nèi)存空間;
  • 為無關聯(lián)的進程提供共享內(nèi)存空間,一般也是將一個普通文件映射到內(nèi)存中。

到此這篇關于Python中mmap模塊(處理大文本)的文章就介紹到這了,更多相關Python中mmap模塊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Python+folium繪制精美地圖的示例詳解

    Python+folium繪制精美地圖的示例詳解

    folium是一個基于leaflet.js的python地圖庫,可以通過folium來操縱數(shù)據(jù),并將其可視化。本文將通過各種示例詳細講解如何利用folium繪制精美地圖,需要的可以參考一下
    2022-03-03
  • Python利用多進程將大量數(shù)據(jù)放入有限內(nèi)存的教程

    Python利用多進程將大量數(shù)據(jù)放入有限內(nèi)存的教程

    這篇文章主要介紹了Python利用多進程將大量數(shù)據(jù)放入有限內(nèi)存的教程,使用了multiprocessing和pandas來加速內(nèi)存中的操作,需要的朋友可以參考下
    2015-04-04
  • Python實現(xiàn)漸變色的水平堆疊圖

    Python實現(xiàn)漸變色的水平堆疊圖

    這篇文章主要為大家詳細介紹了Python實現(xiàn)漸變色的水平堆疊圖,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • python中and和or邏輯運算符的用法示例

    python中and和or邏輯運算符的用法示例

    python中的邏輯運算符有兩種返回值,python運算符除了能操作bool類型表達式,還能操作其他所有類型的表達式,這篇文章主要給大家介紹了關于python中and和or邏輯運算符用法的相關資料,需要的朋友可以參考下
    2022-01-01
  • python如何統(tǒng)計代碼運行的時長

    python如何統(tǒng)計代碼運行的時長

    這篇文章主要介紹了python如何統(tǒng)計代碼運行的時長,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • PyCharm安裝Markdown插件的兩種方法

    PyCharm安裝Markdown插件的兩種方法

    Markdown是一種可以使用普通文本編輯器編寫的標記語言,通過簡單的標記語法,它可以使普通文本內(nèi)容具有一定的格式。這篇文章主要介紹了PyCharm安裝Markdown插件的兩種方法,需要的朋友可以參考下
    2019-06-06
  • python查看列的唯一值方法

    python查看列的唯一值方法

    今天小編就為大家分享一篇python查看列的唯一值方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • Python實現(xiàn)圖片添加文字

    Python實現(xiàn)圖片添加文字

    這篇文章主要為大家詳細介紹了Python實現(xiàn)圖片添加文字,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • 解決python繪圖使用subplots出現(xiàn)標題重疊的問題

    解決python繪圖使用subplots出現(xiàn)標題重疊的問題

    這篇文章主要介紹了python繪圖使用subplots出現(xiàn)標題重疊的問題及解決方法,本文通過實例圖文相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Linux環(huán)境下安裝python3

    Linux環(huán)境下安裝python3

    這篇文章介紹了Linux環(huán)境下安裝python3的方法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07

最新評論