Профилирование генераторов Python
Я адаптирую приложение, которое интенсивно использует генераторы для получения результатов, чтобы обеспечить веб-интерфейс web.py.
До сих пор я мог обернуть вызов для цикла for и операторов, производящих вывод, в функцию и вызвать ее, используя cProfile.run()
или же runctx()
, Концептуально:
def output():
for value in generator():
print(value)
cProfile.run('output()')
В web.py мне нужно обернуть его следующим образом, так как я хочу немедленно выводить результаты потенциально длительных вычислений на каждом шаге итерации, используя yield
:
class index:
def GET(self):
for value in generator():
yield make_pretty_html(value)
Есть ли способ профилировать все вызовы к генератору, как в первом примере, когда он используется, как во втором?
3 ответа
Я наконец нашел решение. Возвращаем значение профилирования через здесь.
import cProfile
import pstats
import glob
import math
def gen():
for i in range(1, 10):
yield math.factorial(i)
class index(object):
def GET(self):
p = cProfile.Profile()
it = gen()
while True:
try:
nxt = p.runcall(next, it)
except StopIteration:
break
print nxt
p.print_stats()
index().GET()
Я также мог бы объединить несколько таких результатов профилирования (как только я начну давать уникальные имена файлов) через документацию и хранить / анализировать их вместе.
Похоже, вы пытаетесь профилировать каждый вызов на "следующий" на генераторе? Если это так, вы можете обернуть ваш генератор в генератор профилирования. Примерно так, где закомментированная часть будет отправлять результаты в журнал или базу данных.
def iter_profiler(itr):
itr = iter(itr)
while True:
try:
start = time.time()
value = itr.next()
end = time.time()
except StopIteration:
break
# do something with (end - stop) times here
yield value
Тогда вместо создания вашего генератора как generator()
вы бы использовали iter_profiler(generator())
Вы можете просто использовать time.time() для профилирования интересующих вас деталей? Просто получите текущее время и вычтите из последнего раза, когда вы сделали измерение.