1. 程式人生 > 實用技巧 >圍觀大神的檔案讀取操作

圍觀大神的檔案讀取操作

小白版

在沒看到大神檔案處理操作的時候,我處理檔案操作的程式碼風格都是如下

# 讀取小檔案
with open('file_path','rb') as f:
    content = f.read()
    # TODO 邏輯處理...
    
    
# 讀取大檔案
with open('file_path','rb') as f:
    for line in f:       
    	# TODO 邏輯處理...
        
# 處理極端情況,大檔案且資料都在一行中
with open('file_path','rb') as f:
    block_size = 1024*8
    while 1:
        chunk = f.read(block_size)
        if not chunk:
            break
        # TODO 邏輯處理...

初級版

利用生成器,解耦讀取和生成

def file_reader(fp,block_size=1024*8):
    while 1:
        chunk = fp.read(block_size)
        if not chunk:
            break
        yield chunk
        
              
def handle_data(fpath):
    with open(fpath,'rb') as f:
        for chunk in file_reader(f)
        	# TODO 邏輯處理...

高階版

似乎看了上面的程式碼,感覺沒啥改進的了,其實不然,iter()是一個用來構造迭代器的內建函式,但它還有一個方法,iter(callable,sentinel),會返回一個特殊的物件,迭代它將不斷產生callable的呼叫結果,直到結果為sentinel為止

def file_reader(fp,block_size=1024*8):
    # 利用partial只是方便構造一個不用傳入引數的函式而已
    # 迴圈不斷返回fp.read的結果,直到結果為''則停止迭代
    for chunk in iter(partial(fp.read,block_size),'')
    	yield chunk

最後

上面的讀取操作只用了2行解決,那麼效能到底如何呢,從一開始的迴圈讀取到生成器,效率提升了近4倍,記憶體佔用更是不到原來的百分之一