python讀取檔案指定行的三種方法

小小程序员ol發表於2024-04-28

1.行遍歷實現

在python中如果要將一個檔案完全載入到記憶體中,透過file.readlines()即可,但是在檔案佔用較高時,我們是無法完整的將檔案載入到記憶體中的,這時候就需要用到python的file.readline()進行迭代式的逐行讀取:

filename = 'hello.txt'
 
with open(filename, 'r') as file:
    line = file.readline()
    counts = 1
    while line:
        if counts >= 50000000:
            break
        line = file.readline()

        counts += 1

這裡我們的實現方式是先用一個with語句開啟一個檔案,然後用readline()函式配合while迴圈逐行載入,最終透過一個序號標記來結束迴圈遍歷,輸出檔案第50000000行的內容。該程式碼的執行效果如下:

dechin@ubuntu2004:~/projects/gitlab/dechin/$ time python3 get_line.py 
 
real    0m10.359s
user    0m10.062s

sys     0m0.296s

可以看到這裡的耗時為10s多一些。

2.linecache實現

雖然在python的readline函式中並沒有實現讀取指定行內容的方案,但是在另一個庫linecache中是實現了的,由於使用的方式較為簡單,這裡直接放上程式碼示例供參考:

filename = 'hello.txt'
 
import linecache

text = linecache.getline(filename, 50000000)

該程式碼的執行結果如下:

dechin@ubuntu2004:~/projects/gitlab/dechin/$ time python3 get_line.py 
 
real    0m11.904s
user    0m5.672s

sys     0m6.231s

雖然在實現方式上簡化了許多,但是我們發現這個實現的用時超過了11s,還不如我們自己手動實現的迴圈遍歷方案。因此如果是對於效能有一定要求的場景,是不建議採用這個方案的。

3.命令列sed獲取

我們知道用Linux系統本身自帶的sed指令也是可以獲取到檔案指定行或者是指定行範圍的資料的,其執行指令為:sed -n 50000000p filename即表示讀取檔案的第50000000行的內容。同時結合python的話,我們可以在python程式碼中執行系統指令並獲取輸出結果:

filename = 'hello.txt'
 
import os

result = os.popen('sed -n {}p {}'.format(50000000, filename)).read()

需要注意的是,如果直接執行os.system()是沒有返回值的,只有os.popen()是有返回值的,並且需要在尾巴加上一個read()的選項。該程式碼的執行結果如下:

dechin@ubuntu2004:~/projects/gitlab/dechin/$ time python3 get_line.py 
 
real    0m2.532s
user    0m0.032s

sys     0m0.020s

可以看到直接使用sed指令的執行速度很快,但是用這種方法並不是一本萬利的,比如以下這個例子:

filename = 'hello.txt'
 
import os

#學習中遇到問題沒人解答?小編建立了一個Python學習交流群:153708845
result = os.popen('sed -n {}p {}'.format(500, filename)).read()

我們把讀取第50000000行內容改為讀取第500行的內容,再執行一次程式:

dechin@ubuntu2004:~/projects/gitlab/dechin/$ time python3 get_line.py 
 
real    0m2.540s
user    0m0.037s

sys     0m0.013s

然而我們發現這個速度並沒有因為要讀取的行數減少了而變少,而是幾乎保持不變的。

總結

本文透過4個測試案例分析了在python中讀取檔案指定行內容的方案,並得到了一些執行耗時的資料。從需求上來說,如果是對於小規模的資料,比如幾百行規模的資料,建議使用readline迴圈遍歷來操作,速度也相當不錯,或者是linecache中的函式實現也是可以的,甚至可以直接用readlines將整個文字內容載入到記憶體中。但是對於資料規模比較大的場景,比如超過了千萬行的級別,那麼使用sed指令的方式對指定行內容進行讀取的方式,應該是所有方式中最快速的。

相關文章