Python inspect.stack работает медленно

Я просто профилировал свою программу Python, чтобы понять, почему она кажется довольно медленной. Я обнаружил, что большая часть времени его работы была потрачена на метод inspect.stack() (для вывода отладочных сообщений с модулями и номерами строк) - 0,005 секунды на вызов. Это кажется довольно высоким; inspect.stack действительно так медленно, или что-то не так с моей программой?


person dpitch40    schedule 01.07.2013    source источник


Ответы (2)


inspect.stack() выполняет две функции:

  • собрать стек, запросив у интерпретатора кадр стека у вызывающего (sys._getframe(1)), а затем следуя всем .f_back ссылкам. Это дешево.

  • для каждого кадра, соберите имя файла, номер файла и контекст исходного файла (строка исходного файла плюс несколько дополнительных строк вокруг нее, если требуется). Последнее требует чтения исходного файла для каждого кадра стека. Это дорогостоящий шаг.

Чтобы отключить загрузку контекста файла, установите для параметра context значение 0:

inspect.stack(0)

Даже с контекстом, установленным в 0, вы все равно получаете доступ к файловой системе для каждого кадра, поскольку имя файла определяется и проверяется на существование для каждого кадра.

person Martijn Pieters    schedule 01.07.2013
comment
Это сократило время, затрачиваемое на метод inspect.stack, примерно в 5 раз. С этого момента, я думаю, я буду работать только над уменьшением количества регистрируемых отладочных сообщений (или их объединением). Спасибо за информацию. - person dpitch40; 01.07.2013

inspect.stack(0) может быть быстрее, чем inspect.stack(). Тем не менее, проще всего вообще не вызывать его и, возможно, использовать вместо этого такой шаблон:

frame = inspect.currentframe()
while frame:
    if has_what_i_want(frame):  # customize
        return what_i_want(frame)  # customize
    frame = frame.f_back

Обратите внимание, что последний frame.f_back равен None, и тогда цикл завершится.

sys._getframe(1), очевидно, не следует использовать, потому что это внутренний метод.

В качестве альтернативы можно выполнить цикл inspect.getouterframes(inspect.currentframe()), но ожидается, что это будет медленнее, чем описанный выше подход.

person Acumenus    schedule 06.03.2017