2016-09-09 70 views
3

說我從兩個數組印數到一個文件:如何加快逐行打印到Python中的文件?

from numpy import random 
number_of_points = 10000 
a = random.rand(number_of_points) 
b = random.rand(number_of_points) 
fh = open('file.txt', 'w') 
for i in range(number_of_points): 
    for j in range(number_of_points): 
     print('%f %f' % (a[i], b[j]), file=fh) 

我覺得這是賺很多調用系統打印的,而發送包含該信息會更快的呼叫。它是否正確?如果是這樣,我怎麼能這樣做?有更快的方法來實現這個嗎?

+1

它有多慢?經過測試,你是否確定它對於你的目的來說太慢了?如果是這樣,你確定罪魁禍首是重複的「打印」電話?你有沒有試過'print('\ n'.join(['%f%f'%(a [i],b [i])in range(number_of_points)])''? – TigerhawkT3

+0

在我的應用程序中,這個部分的任何速度改進都是需要的。分析引腳'print'是罪魁禍首。我將如何做以上的嵌套for循環?上面編輯包含嵌套'for'循環。 – bfletch

+0

@ TigerhawkT3:這個建議會在內存中創建一個100M的'str'列表,以及一個'str',它們的總長度都是所需的峯值RAM。這是需要多GB的內存,比許多系統擁有的要多。你不想用一種不會零碎寫的解決方案來解決這個問題。 – ShadowRanger

回答

2

print有很多你不使用的花裏胡哨的東西,你正在使用C風格的循環索引而不是直接迭代,這兩者都增加了不必要的開銷。您可以通過限制Python級別的工作,將其推到C層來加快速度。

例如,在這種情況下,你可以更換整個雙重嵌套循環結構:

import itertools 

# You could use '%f %f\n'.__mod__ as the map function if you like, I just 
# find the modern format strings a little nicer 
fh.writelines(itertools.starmap('{} {}\n'.format, itertools.product(a, b))) 

它使用product直接產生的嵌套循環的結果和索引,starmap + str.format創建這些行和fh.writelines用於耗盡由starmap創建的發生器,將其所有輸出直接寫入文件,而不是使用單個函數調用,而不是100,000,000次調用至print

除了創建生成器並將最終生成器傳遞到fh.writelines的固定(與迭代的項數無關)設置成本之外,實際的迭代,格式化和I/O工作將完全發生在CPython參考解釋器,所以它應該運行得非常快。

+0

即使沒有itertools(這可能不適合OP的真實代碼以及他的例子)。使用'file.write'是一個很好的提示。它的印刷速度可能會快兩倍。 – tdelaney

+0

@tdelaney'io.TextIOBase.write(s)'和'io.IOBase.writelines(lines)'與'print()'相比有什麼性能優勢?看起來'print()'和'io.TextIOBase.write(s)'都是逐行緩衝的,而'io.IOBase.writelines(lines)'緩衝區用於所有行?它是否正確? – bfletch

+1

@bfletch我不知道爲什麼'print'更慢,但它不是行緩衝的問題。文件打開時決定緩衝。終端默認爲行緩衝,而文件和管道默認爲阻止緩衝 - 您的打印不是行緩衝。我在一次測試中將文件緩衝區大小增加到16兆,並且即使系統寫入數量下降了2000倍,總體執行時間仍然保持不變,當我改寫爲'write'時,執行時間減少了〜40% 。所以,它的「印刷」速度很慢,而不是系統緩衝。你的旅費可能會改變! – tdelaney

相關問題