2016-04-23 59 views
1

我想比較處理一個流作爲過濾器(即獲得一點,過程,漂洗),反對sl((即獲取所有信息,然後處理)的效果。在Python中讀取文件:slurp或filter?

但是,當我運行下面的兩個代碼時,我得到了類似的結果。我期待在slurp版本中獲得更糟糕的結果。

下面的代碼片段是否如上所述做了任何不同的事情?如果它們相同,我怎麼能適應其中的一個來測試過濾器/污水差異?

我與測試腳本:

jot 100000000 | time python3 dont_slurp.py > /dev/null 
jot 100000000 | time python3 slurp.py > /dev/null 

Jot生成號碼從1到x。代碼片段只是計算線條。

篩選:

import sys 
lineno = 0 
for line in sys.stdin: 
    lineno += 1 
    print("{:>6} {}".format(lineno, line[:-1])) 

啜食:

所有的
import sys 

f = sys.stdin 
lineno = 0 

for line in f: 
    lineno += 1 
    print('{:>6} {}'.format(lineno, line[:-1])) 
+2

「Slurp」版本沒有做你認爲的事。兩個版本一次只讀一行。要一次讀取所有行,你可以在f.readlines()中執行''。 –

回答

0

首先,你的代碼示例是不是做你的想法。所有f = sys.stdin確實將f設置爲相同的文件句柄。行for line in f:for line in sys.stdin:在功能上是相同的。

你想是什麼:

import sys 

lineno = 0 

for line in sys.stdin.readlines(): 
     lineno += 1 
     print('{:>6} {}'.format(lineno, line[:-1])) 

readlines()返回一個列表,文件中每行一個元素。我相信這是而不是一個生成器,所以你可以得到完整的列表。文件句柄本身作爲一個生成器,一次給你一行。

您應該看到與readline()的性能差異。

但是,答案是「哪個更好?」是「視情況而定」。當您逐行閱讀時,您正在進行系統調用,這又會導致操作系統以塊爲單位從磁盤讀取文件內容。這些塊可能大於平均線的大小,並且該塊可能被緩存。這意味着有時候你會碰到磁盤,花費很多時間,其他時間點擊緩存,花費很少的時間。

當您一次讀取所有內容時,會立即將文件中的每個字節加載到內存中。如果您有足夠的空閒內存來容納所有文件內容,則這需要的時間與逐行版本完全相同。在這兩種情況下,基本上只需要一點點的開銷就可以順序讀取整個文件。

區別在於你沒有足夠的可用內存來容納整個文件。在這種情況下,您會讀取整個文件,但其中的一部分會被虛擬內存系統交換回磁盤。當你訪問該特定行時,它們必須再次被拉入。

確切地說,丟失多少時間取決於正在使用多少內存,系統上正在進行多少其他活動等,因此一般無法對其進行量化。

這是一個情況,你真的不應該擔心它,直到有問題。在代碼中做更自然的事情,如果程序太慢,只擔心性能。

+0

我認爲可以值得指出的一點是,如果進行過濾,您可能能夠並行執行I/O和CPU工作。 –