Строка Python, форматирующая слишком медленный

Я использую следующий код для входа карты, это быстро, когда это только содержит, обнуляет, но как только существуют фактические данные в карте, это становится невыносимо медленным... Там какой-либо путь состоит в том, чтобы сделать это быстрее?

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]))
8
задан wich 14 April 2010 в 13:03
поделиться

3 ответа

Я предлагаю вам запустить свой код с помощью модуля cProfile и обработать результаты постобработкой, как описано в http: // docs. python.org/library/profile.html . Это позволит вам точно узнать, сколько времени уходит на вызов str .__ mod __ для форматирования строки и сколько времени уходит на другие вещи, такие как запись файла и выполнение __ getitem __ ищет map [0] [i] и тому подобное.

3
ответ дан 5 December 2019 в 23:14
поделиться

Сначала я проверил% против обратного цитирования. % быстрее. Тогда я проверил% (кортеж) на 'string'.format (). Первоначальная ошибка заставила меня подумать, что это было быстрее. Но нет. % быстрее.

Итак, вы уже выполняете огромную кучу преобразований чисел с плавающей точкой в ​​строку самым быстрым из возможных способов на Python.

Приведенный ниже демонстрационный код является уродливым демонстрационным кодом. Пожалуйста, не чините мне лекции о xrange против range или другой педантичности. KThxBye.

Мое специальное и крайне ненаучное тестирование показывает, что (a)% (1.234,) операций на Python 2.5 в Linux выполняется быстрее, чем% (1.234, ...) операция Python 2.6 в Linux, для тестового кода ниже, при условии, что попытка использования 'string'.format () не будет работать в версиях python до 2.6. И так далее.

# 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"    

Я думаю, вы могли бы оптимизировать свой код, построив свои ПАКЕТЫ с плавающей запятой где-нибудь в другом месте, где бы вы ни построили эту карту, в первую очередь создайте свой список кортежей, а затем применив кортеж fmt_string% следующим образом:

for tup in mytups:
    log_file.write( fmt_str % tup )

Я был удалось сократить 8,7 секунды до 8,5 секунд, исключив часть создания кортежа из цикла for. Что немного. Большой мальчик есть форматирование с плавающей запятой, которое, я считаю, всегда будет дорогостоящим.

Альтернатива:

Рассматривали ли вы, что НЕ нужно записывать такие огромные журналы, как текст, а вместо этого сохранять их с помощью самого быстрого из доступных методов «сохранения», а затем писать короткую утилиту для вывода их в текст, когда это необходимо? Некоторые люди используют NumPy с очень большими наборами числовых данных, и не похоже, что они будут использовать построчный дамп для хранения своих данных. См .:

http://thsant.blogspot.com/2007/11/saving-numpy-arrays-which-is-fastest.html

2
ответ дан 5 December 2019 в 23:14
поделиться

Не желая углубляться в трясину оптимизации этого кода, я бы написал код, более похожий на этот:

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 .

0
ответ дан 5 December 2019 в 23:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: