python按行遍歷一個大文件,最優的語法應該是什麼?
目前寫了2種方法,
1.2.
for l in file.readlines():
cPython2/3下,一個4百萬行的文件,方法1用了5.1秒,方法2用了5.9秒pypy下,反而是方法2比較快,用了2.1秒,方法1用了3.4秒,不知是for慢了還是readlines慢了
while l:
l = file.readline()
------------------ 2015-03-02 補充 ---------------3. 測試使用的系統是archlinux,用了 cPython2/3 pypy2 三個解釋器,同步到最新版本。經過多次測試,總體來說方法3是最快的。不過具體到解釋器也很重要,也發現一些有趣的現象:
for l in file:
- cPython2下方法3明顯最快
- pypy下方法2和3不相上下,用方法3橫向比較,pypy也是所有解釋器里最快的
- 方法3在cPython3下要比cPython2下要慢一些,並且cPython3下方法3不能用 file.tell() (只有方法2可用),所以如果要顯示進度還挺麻煩。
理論上來說,總體上file.readlines()可以(取決於實現)不慢於你自己手動的一次次調用file.readline(),因為前者的循環在C語言層面,而你的循環是在Python語言層面。
但是在內存佔用上前者可能是後者的好幾十百倍,因為前者會一次性把所有數據讀取到內存中,而後者只每次讀取一行。
更好的寫法是:with open("filename") as file:
for line in file:
do_things(line)
9我不會告訴你,其實直接可以這樣:
file = open(file_name)for line in file: dosomething(line)不過這樣做,每一行會保留換行符補充一下,由於手頭上沒有電腦,我不確定我這種方法是否比你的第一種快,但是你的第一種方法是一次性將文件的內容全部讀進一個list後再用for進行遍歷,而第二種是一次讀取一行處理,所以,第一種比第二種快是在理解範圍內的,至於pypy的問題,我個人的理解是pypy優化while比優化for優化得更多(猜測)。。如果是特大文件的話,不推薦使用第一種方法。
2015年3月1號再次補充
基於嚴謹的科學態度,今天做了測試,我之前提到的方法是不會一次性讀取所有文件的,使用660m的文件進行測試,
for i in file.readlines耗時1.5sfor i in file耗時0.86while file.readline耗時3.3而且,我還發現了一個更加神奇的事情,temp = file.readlinesfor i in temp比直接使用for i in file.readlines要快,耗時1.2s最後測試了不同大小的文件,發現無論是大文件還是小文件,都是直接對文件對象進行for操作是最快的!不過該結論局限於我自己的測試數據除上面說的外,用生成器也可以。
with open("filename") as file:
for line in file:
do_things(line)
這是最快、最安全的方式
沒比較過,我一般用linecache函數
我用專欄里的一篇文章來答題。
專欄鏈接:給妹子講python,歡迎大家關注,提意見!
文件的遍歷
因為文件保存了很多字元和行,因此也是循環常見的典型使用案例,最原始的方法可以調用文件對象的read方法,把文件內容一次性載入至字元串對象
file = open("myfile.txt", "r")
print(file.read())
hello text file
goodbyt text file
Hahahahah
那麼如果想逐行讀取文本文件呢?for循環是最易於編寫及執行最快的選擇,這裡有兩種方法,
for line in open("myfile.txt","r").readlines():
print(line, end="")
for line in open("myfile.txt","r"):
print(line, end="")
hello text file
goodbyt text file
Hahahahah
這兩種方法的運行結果是一樣的,表面差別不大,但實際上有很大的區別:
第一種方法通過readlines方法,會首先一次性把文件載入到行字元串列表中,然後再對這個字元串列表進行迭代;
而第二種方法運行的原理則有所不同,他並非一次性將全部的文件內容載入到內存中,而是在迭代的時候,循環到了哪一行才將哪一行讀入到內存。這裡涉及到一個新的概念----迭代器(open函數返回的那個就是文件迭代器),專欄里的文章會著重系統介紹,歡迎關注。
現在我們只需要知道,第二種方法是文本文件讀取的最佳選擇,它簡單、且對任意大小的文件都有效,因為他不會一次性把整個文件都載入到內存中,相反第一種方法存在內存壓力過大的問題。
推薦閱讀:
※ruby語言有什麼樣的美學特點?
※寫一個實用水平的編譯器有多難,多大工作量?
※直接看 ISO C++14 的標準文檔學習 C++ 可行嗎?
※為什麼很少有用lisp描述演算法?
※c和c++這類沒有gc的語言是不是騙自己?