簡體   English   中英

Python字符串格式化太慢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM