Мне нужно запустить python script в течение некоторого случайного промежутка времени, приостановить его, получить трассировку стека и отключить его. Я искал путь для этого, но я не вижу очевидного решения.
Есть ли статистический профилировщик для python? Если нет, как я могу написать письмо?
Ответ 1
Здесь statprof
модуль
pip install statprof
(или easy_install statprof
), затем используйте:
import statprof
statprof.start()
try:
my_questionable_function()
finally:
statprof.stop()
statprof.display()
Там немного фона на модуле из этого сообщения в блоге:
Зачем это важно? У Python уже есть два встроенных профайлера: lsprof и долговременный hotshot. Проблема с lsprof заключается в том, что он отслеживает только вызовы функций. Если у вас есть несколько горячих циклов внутри функции, lsprof почти бесполезен для определения того, какие из них действительно важны.
Несколько дней назад я оказался в ситуации, в которой lsprof терпит неудачу: он говорил мне, что у меня есть горячая функция, но функция была незнакома мне и достаточно долго, чтобы сразу не было видно, где проблема был.
После немного попрошайничества в Twitter и Google+, кто-то указал мне на statprof. Но была проблема: хотя она делала статистическую выборку (yay!), Она отслеживала только первую строку функции при выборке (wtf!?). Поэтому я исправил это, подтолкнул документацию, и теперь ее можно использовать и не вводить в заблуждение. Вот пример его вывода, более точное определение линии нарушения в этой горячей функции:
% cumulative self time seconds seconds name 68.75 0.14 0.14 scmutil.py:546:revrange 6.25 0.01 0.01 cmdutil.py:1006:walkchangerevs 6.25 0.01 0.01 revlog.py:241:__init__ [...blah blah blah...] 0.00 0.01 0.00 util.py:237:__get__ --- Sample count: 16 Total time: 0.200000 seconds
Я загрузил statprof в индекс пакета Python, поэтому его почти тривиально установить: "easy_install statprof" и вы запускаетесь.
Так как код включен в github, пожалуйста, примите во внимание сообщения об ошибках и улучшения. Наслаждайтесь!
Ответ 2
Я могу придумать пару нескольких способов сделать это:
-
Вместо того, чтобы пытаться получить трассировку стека во время работы программы, просто запустите на нее прерывание и проанализируйте вывод. Вы можете сделать это с помощью оболочки script или с другим python script, который вызывает ваше приложение в качестве подпроцесса. Основная идея объясняется и довольно тщательно защищена в этом ответе на вопрос, связанный с С++.
- Собственно, вместо того, чтобы анализировать вывод, вы можете зарегистрировать процедуру postmortem (используя
sys.excepthook
), которая регистрирует трассировку стека, К сожалению, у Python нет пути для продолжения с момента возникновения исключения, поэтому вы не можете возобновить выполнение после ведения журнала.
- Собственно, вместо того, чтобы анализировать вывод, вы можете зарегистрировать процедуру postmortem (используя
-
Чтобы фактически получить трассировку стека из запущенной программы, вам может понадобиться выполнить для взлома реализации. Поэтому, если вы действительно этого хотите, может быть стоит потратить ваше время, чтобы проверить pypy, реализацию Python, написанную в основном на Python. Я понятия не имею, как удобно было бы это делать в pypy. Я предполагаю, что это было бы не особенно удобно, так как это включало бы введение крюка в основном каждую инструкцию, которая, по-моему, была бы непозволительно неэффективной. Кроме того, я не думаю, что будет намного больше преимуществ по сравнению с первым вариантом, если только не потребуется очень много времени, чтобы достичь состояния, в котором вы хотите начать трассировку стека.
-
Существует набор макросов для отладчика
gdb
, предназначенный для облегчения отладки самого Python. gdb может присоединяться к внешнему процессу (в данном случае экземпляру python, который выполняет ваше приложение), и, действительно, почти что-либо с ним. Кажется, что макросpystack
предоставит вам обратную линию стека Python в текущей точке выполнения. Я думаю, что было бы легко автоматизировать эту процедуру, так как вы можете (в худшем случае) просто передать текст вgdb
с помощьюexpect
или что-то еще.
Ответ 3
Python уже содержит все, что вам нужно, чтобы сделать то, что вы описали, не нужно взламывать интерпретатор.
Вам просто нужно использовать модуль traceback
в сочетании с sys._current_frames()
. Все, что вам нужно, - это способ сбросить трассировку, которая вам нужна, на нужную вам частоту, например, используя сигналы UNIX или другой поток.
Чтобы начать свой код, вы можете сделать именно то, что сделано в this commit:
-
Скопируйте модуль
threads.py
из этой фиксации или, по крайней мере, функцию демпинга трассировки стека (лицензия ZPL, очень либеральная ): -
Подключите его к обработчику сигналов, скажем,
SIGUSR1
Тогда вам просто нужно запустить свой код и "убить" его с помощью SIGUSR1 так часто, как вам нужно.
В случае, когда одна функция одного потока "выборочно" время от времени использует тот же метод, используя другой поток для синхронизации, я предлагаю проанализировать код Products.LongRequestLogger и его тесты (разработанные вами по-настоящему, в то время как при использовании Nexedi):
Независимо от того, является ли это надлежащим "статистическим" профилированием, ответ Майком Данлави, на который ссылается intuited делает убедительный аргумент в пользу того, что это очень мощная техника "отладки производительности", и у меня есть личный опыт, который действительно помогает быстро увеличить реальные причины производительности вопросы.
Ответ 4
Чтобы реализовать внешний статистический профилировщик для Python, вам понадобятся некоторые общие инструменты отладки, которые позволяют вам опросить другой процесс, а также некоторые специальные инструменты Python, чтобы удержать состояние интерпретатора.
Это не простая проблема в общем, но вы можете попробовать начать с GDB 7 и связанных с ним инструментов анализа CPython.
Ответ 5
Существует кросс-платформенный выборка (статистический) профилировщик Python, написанный на C под названием vmprof-python. Разработанный членами команды PyPy, он поддерживает PyPy, а также CPython. Он работает на Linux, Mac OSX и Windows. Он написан на C, поэтому имеет очень небольшие накладные расходы. Он описывает код Python, а также собственные вызовы, выполненные из кода Python. Кроме того, у него есть очень полезная опция для сбора статистики о строках выполнения внутри функций в дополнение к именам функций. Он также может использовать профилирование памяти (путем отслеживания размера кучи).
Он может быть вызван из кода Python через API или из консоли. Для просмотра дампов профиля есть веб-интерфейс: vmprof.com, который также open sourced.
Кроме того, некоторые IDE Python (например, PyCharm) имеют интеграцию с ним, что позволяет запускать профилировщик и видеть результаты в редакторе.
Ответ 6
Через семь лет после того, как вопрос был задан, для Python теперь доступно несколько хороших статистических профилировщиков. Помимо vmprof, уже упомянутого Дмитрием Трофимовым в этом ответе, существуют также vprof и pyflame. Все они так или иначе поддерживают графики пламени, давая вам хороший обзор того, где было потрачено время.
Ответ 7
Austin - это сэмплер стека фреймов для CPython, который можно использовать для создания статистических профилировщиков для Python, которые не требуют инструментов и вводят минимальные накладные расходы. Самое простое, что нужно сделать, это передать вывод Остина с FlameGraph. Тем не менее, вы можете просто получить выход Austin с помощью специального приложения, чтобы создать свой собственный профилировщик, который точно соответствует вашим потребностям.
Это скриншот Austin TUI, терминального приложения, которое обеспечивает вид сверху всего, что происходит внутри работающего приложения Python.
Это Web Austin, веб-приложение, которое показывает график в реальном времени собранных образцов. Вы можете настроить адрес, по которому приложение будет обслуживать приложение, что позволит вам выполнять удаленное профилирование.