Профилирование генераторов 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() для профилирования интересующих вас деталей? Просто получите текущее время и вычтите из последнего раза, когда вы сделали измерение.

Другие вопросы по тегам