[英]Python string formatting too slow
我使用下面的代碼來記錄一個映射,當它僅包含零時它是快速的,但是一旦映射中有實際數據,它就會變得令人難以忍受的緩慢……有什么方法可以更快地這樣做嗎?
log_file = open('testfile', 'w')
for i, x in ((i, start + i * interval) for i in range(length)):
log_file.write('%-5d %8.3f %13g %13g %13g %13g %13g %13g\n' % (i, x,
map[0][i], map[1][i], map[2][i], map[3][i], map[4][i], map[5][i]))
建議您使用cProfile
模塊運行代碼, cProfile
結果進行后處理,如http://docs.python.org/library/profile.html所述 。 這將使您確切知道調用str.__mod__
進行字符串格式化所花費的時間,以及執行其他操作所花費的時間,例如編寫文件以及對map[0][i]
進行__getitem__
查找等等。 。
首先,我檢查了%是否有反引號。 % 是比較快的。 然后我檢查了%(元組)是否與'string'.format()相對。 最初的錯誤使我認為它更快。 但不是。 % 是比較快的。
因此,您已經在以Python最快的方式進行了大量的浮點到字符串轉換。
下面的演示代碼是丑陋的演示代碼。 請不要教我關於xrange與range或其他方法的比較。 KThxBye。
我的即席且高度不科學的測試表明,對於下面的測試代碼,帶有(a)在Linux上的Python 2.5上執行%(1.234,)操作比在Linux上的%(1.234,...)操作上更快。嘗試在2.6之前的python版本上使用'string'.format()無效。 等等。
# this code should never be used in production.
# should work on linux and windows now.
import random
import timeit
import os
import tempfile
start = 0
interval = 0.1
amap = [] # list of lists
tmap = [] # list of tuples
def r():
return random.random()*500
for i in xrange(0,10000):
amap.append ( [r(),r(),r(),r(),r(),r()] )
for i in xrange(0,10000):
tmap.append ( (r(),r(),r(),r(),r(),r()) )
def testme_percent():
log_file = tempfile.TemporaryFile()
try:
for qmap in amap:
s = '%g %g %g %g %g %g \n' % (qmap[0], qmap[1], qmap[2], qmap[3], qmap[4], qmap[5])
log_file.write( s)
finally:
log_file.close();
def testme_tuple_percent():
log_file = tempfile.TemporaryFile()
try:
for qtup in tmap:
s = '%g %g %g %g %g %g \n' % qtup
log_file.write( s );
finally:
log_file.close();
def testme_backquotes_rule_yeah_baby():
log_file = tempfile.TemporaryFile()
try:
for qmap in amap:
s = `qmap`+'\n'
log_file.write( s );
finally:
log_file.close();
def testme_the_new_way_to_format():
log_file = tempfile.TemporaryFile()
try:
for qmap in amap:
s = '{0} {1} {2} {3} {4} {5} \n'.format(qmap[0], qmap[1], qmap[2], qmap[3], qmap[4], qmap[5])
log_file.write( s );
finally:
log_file.close();
# python 2.5 helper
default_number = 50
def _xtimeit(stmt="pass", timer=timeit.default_timer,
number=default_number):
"""quick and dirty"""
if stmt<>"pass":
stmtcall = stmt+"()"
ssetup = "from __main__ import "+stmt
else:
stmtcall = stmt
ssetup = "pass"
t = timeit.Timer(stmtcall,setup=ssetup)
try:
return t.timeit(number)
except:
t.print_exc()
# no formatting operation in testme2
print "now timing variations on a theme"
#times = []
#for i in range(0,10):
n0 = _xtimeit( "pass",number=50)
print "pass = ",n0
n1 = _xtimeit( "testme_percent",number=50);
print "old style % formatting=",n1
n2 = _xtimeit( "testme_tuple_percent",number=50);
print "old style % formatting with tuples=",n2
n3 = _xtimeit( "testme_backquotes_rule_yeah_baby",number=50);
print "backquotes=",n3
n4 = _xtimeit( "testme_the_new_way_to_format",number=50);
print "new str.format conversion=",n4
# times.append( n);
print "done"
我認為您可以通過在其他任何地方構建浮點數TUPLES來優化您的代碼,無論您在哪個地方構建該地圖,首先構建元組列表,然后以這種方式應用fmt_string%元組:
for tup in mytups:
log_file.write( fmt_str % tup )
通過將for-tuple部分從for循環中刪除,我能夠將8.7秒減少到8.5秒。 沒什么。 那里的大個子有浮點格式,我相信這總是很昂貴的。
選擇:
您是否考慮過不編寫諸如文本之類的龐大日志,而是使用可用的最快“持久性”方法保存它們,然后編寫一個簡短的實用程序以在需要時將其轉儲為文本? 有些人將NumPy與非常大的數字數據集一起使用,而且似乎不願意使用逐行轉儲來存儲其內容。 看到:
http://thsant.blogspot.com/2007/11/saving-numpy-arrays-which-is-fastest.html
不希望涉入優化此代碼的麻煩,我會像這樣編寫代碼:
log_file = open('testfile', 'w')
x = start
map_iter = zip(range(length), map[0], map[1], map[2], map[3], map[4], map[5])
fmt = '%-5d %8.3f %13g %13g %13g %13g %13g %13g\n'
for i, m0, m1, m2, m3, m4, m5 in mapiter:
s = fmt % (i, x, m0, m1, m2, m3, m4, m5)
log_file.write(s)
x += interval
但我會建議不要在python內置函數之后給變量命名,例如map
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.