Документация Python неофициальный перевод

profiling.tracing.md

255 строк · 19.3 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.15/library/profiling.tracing.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `profiling.tracing` – Детерминированный профилировщик89Добавлено в версии 3.15.1011**Исходный код:** [Lib/profiling/tracing/](https://python-all.ru/src/3.15/Lib/profiling/tracing)1213---1415Модуль `profiling.tracing` обеспечивает детерминированное профилирование программ на Python. Он отслеживает каждый вызов функции, возврат из функции и событие исключения, записывая точное время для каждого. Такой подход даёт точные счётчики вызовов и полную видимость выполнения программы, что делает его идеальным для разработки и тестирования.1617> **Примечание**18>19> Этот модуль также доступен как `cProfile` для обратной совместимости. Имя `cProfile` будет продолжать работать во всех будущих версиях Python. Используйте тот стиль импорта, который подходит вашему коду:20>21> ```python22> # Рекомендуемый (новый стиль)23> import profiling.tracing24> profiling.tracing.run('my_function()')25>26> # Также работает (обратная совместимость)27> import cProfile28> cProfile.run('my_function()')29> ```3031## Что такое детерминированное профилирование?3233*Детерминированное профилирование* фиксирует каждый вызов функции, возврат из функции и событие исключения во время выполнения программы. Профилировщик измеряет точные временные интервалы между этими событиями, предоставляя точную статистику о том, как программа ведёт себя.3435В отличие от [статистического профилирования](https://python-all.ru/3.15/library/profiling.sampling.html#profiling-sampling), которое периодически опрашивает стек вызовов для оценки затрат времени, детерминированное профилирование записывает каждое событие. Это означает, что вы получаете точные счётчики вызова, а не статистические приближения. Оборотная сторона в том, что инструментирование каждого события вносит накладные расходы, которые могут замедлить выполнение программы.3637Интерпретируемая природа Python делает детерминированное профилирование практичным. Интерпретатор уже диспетчеризует события для вызовов и возвратов функций, поэтому профилировщик может подключиться к этому механизму без необходимости изменения кода. Накладные расходы обычно невелики по сравнению с внутренними затратами на интерпретацию, что делает детерминированное профилирование подходящим для большинства рабочих процессов разработки.3839Детерминированное профилирование помогает ответить на такие вопросы, как:4041- Сколько раз была вызвана эта функция?42- Каков полный граф вызовов моей программы?43- Какие функции вызываются конкретной функцией?44- Происходят ли неожиданные вызовы функций?4546Статистика счётчиков вызовов может выявить ошибки (неожиданные значения) и возможности для встраивания (высокие счётчики вызовов). Статистика внутреннего времени показывает «горячие циклы», требующие оптимизации. Статистика кумулятивного времени помогает выявить алгоритмическую неэффективность. Обработка кумулятивного времени в этом профилировщике позволяет напрямую сравнивать рекурсивные и итеративные реализации.4748## Интерфейс командной строки4950Модуль `profiling.tracing` можно вызвать как сценарий для профилирования другого сценария или модуля:5152```console53python -m profiling.tracing [-o output_file] [-s sort_order] (-m module | script.py)54```5556Это запускает указанный сценарий или модуль под профилировщиком и выводит результаты в стандартный вывод (или сохраняет их в файл).5758#### `-o <output_file>`5960Записывает результаты профилирования в файл, а не в стандартный вывод. Выходной файл может быть прочитан модулем [`pstats`](https://python-all.ru/3.15/library/pstats.html#module-pstats) для последующего анализа.6162#### `-s <sort_order>`6364Сортирует вывод по указанному ключу. Принимает любой из ключей сортировки, распознаваемых [`pstats.Stats.sort_stats()`](https://python-all.ru/3.15/library/pstats.html#pstats.Stats.sort_stats), таких как `cumulative`, `time`, `calls` или `name`. Этот параметр применяется только если [`-o`](https://python-all.ru/3.15/library/profiling.tracing.html#cmdoption-profiling.tracing-o) не указан.6566#### `-m <module>`6768Профилирует модуль вместо сценария. Модуль находится с помощью стандартного механизма импорта.6970Добавлено в версии 3.7: Параметр `-m` для `cProfile`.7172Добавлено в версии 3.8: Параметр `-m` для [`profile`](https://python-all.ru/3.15/library/profile.html#module-profile).7374## Примеры программного использования7576Для более тонкого управления профилированием используйте функции и классы модуля напрямую.7778### Основное профилирование7980Самый простой подход – использовать функцию `run()`:8182```python83import profiling.tracing84profiling.tracing.run('my_function()')85```8687Это профилирует переданную строку кода и выводит сводку в стандартный вывод. Чтобы сохранить результаты для последующего анализа:8889```python90profiling.tracing.run('my_function()', 'output.prof')91```9293### Использование `Profile` класса9495Класс `Profile` обеспечивает детальный контроль:9697```python98import profiling.tracing99import pstats100from io import StringIO101102pr = profiling.tracing.Profile()103pr.enable()104# ... код для профилирования ...105pr.disable()106107# Вывести результаты108s = StringIO()109ps = pstats.Stats(pr, stream=s).sort_stats(pstats.SortKey.CUMULATIVE)110ps.print_stats()111print(s.getvalue())112```113114Класс `Profile` также работает как менеджер контекста:115116```python117import profiling.tracing118119with profiling.tracing.Profile() as pr:120    # ... код для профилирования ...121122pr.print_stats()123```124125## Справочник модуля126127#### `profiling.tracing.run(command, filename=None, sort=-1)`128129Профилирует выполнение команды и выводит или сохраняет результаты.130131Эта функция выполняет строку *command* с помощью [`exec()`](https://python-all.ru/3.15/library/functions.html#exec) в пространстве имён модуля `__main__`:132133```python134exec(command, __main__.__dict__, __main__.__dict__)135```136137Если *filename* не указан, функция создаёт экземпляр [`pstats.Stats`](https://python-all.ru/3.15/library/pstats.html#pstats.Stats) и выводит сводку в стандартный вывод. Если *filename* указан, необработанные данные профиля сохраняются в этот файл для последующего анализа с помощью [`pstats`](https://python-all.ru/3.15/library/pstats.html#module-pstats).138139Аргумент *sort* задаёт порядок сортировки для выводимых данных, принимая любое значение, распознаваемое [`pstats.Stats.sort_stats()`](https://python-all.ru/3.15/library/pstats.html#pstats.Stats.sort_stats).140141#### `profiling.tracing.runctx(command, globals, locals, filename=None, sort=-1)`142143Профилирует выполнение команды с явными пространствами имён.144145Как [`run()`](https://python-all.ru/3.15/library/profiling.tracing.html#profiling.tracing.run), но выполняет команду с указанными отображениями *globals* и *locals* вместо использования пространства имён модуля `__main__`:146147```python148exec(command, globals, locals)149```150151#### `class profiling.tracing.Profile(timer=None, timeunit=0.0, subcalls=True, builtins=True)`152153Объект профилировщика, собирающий статистику выполнения.154155Необязательный аргумент *timer* задаёт пользовательскую функцию замера времени. Если он не указан, профилировщик использует таймер по умолчанию, подходящий для платформы. При передаче пользовательского таймера он должен возвращать одно число, представляющее текущее время. Если таймер возвращает целые числа, используйте *timeunit*, чтобы указать длительность одной единицы времени (например, `0.001` для миллисекунд).156157Аргумент *subcalls* управляет тем, отслеживает ли профилировщик отношения вызовов между функциями. Аргумент *builtins* управляет тем, профилируются ли встроенные функции.158159Изменено в версии 3.8: Добавлена поддержка контекстного менеджера.160161#### `enable()`162163Начинает сбор данных профилирования.164165#### `disable()`166167Прекращает сбор данных профилирования.168169#### `create_stats()`170171Прекращает сбор данных и сохраняет результаты внутри как текущий профиль.172173#### `print_stats(sort=-1)`174175Создаёт объект [`pstats.Stats`](https://python-all.ru/3.15/library/pstats.html#pstats.Stats) из текущего профиля и выводит результаты в стандартный вывод.176177Аргумент *sort* задаёт порядок сортировки. Он принимает один ключ или кортеж ключей для многоуровневой сортировки, используя те же значения, что и [`pstats.Stats.sort_stats()`](https://python-all.ru/3.15/library/pstats.html#pstats.Stats.sort_stats).178179Добавлено в версии 3.13: Поддержка кортежа ключей сортировки.180181#### `dump_stats(filename)`182183Записывает текущие данные профиля в *filename*. Файл может быть прочитан с помощью [`pstats.Stats`](https://python-all.ru/3.15/library/pstats.html#pstats.Stats) для последующего анализа.184185#### `run(cmd)`186187Профилирует строку команды с помощью [`exec()`](https://python-all.ru/3.15/library/functions.html#exec).188189#### `runctx(cmd, globals, locals)`190191Профилирует строку команды с помощью [`exec()`](https://python-all.ru/3.15/library/functions.html#exec) с указанными пространствами имён.192193#### `runcall(func, /, *args, **kwargs)`194195Профилирует вызов функции. Возвращает то, что возвращает *func*:196197```python198result = pr.runcall(my_function, arg1, arg2, keyword=value)199```200201> **Примечание**202>203> Для профилирования необходимо, чтобы профилируемый код завершился нормально. Если интерпретатор завершится (например, через [`sys.exit()`](https://python-all.ru/3.15/library/sys.html#sys.exit)) во время профилирования, результаты получены не будут.204205## Использование пользовательского таймера206207Класс [`Profile`](https://python-all.ru/3.15/library/profiling.tracing.html#profiling.tracing.Profile) принимает пользовательскую функцию таймера, позволяя измерять различные аспекты выполнения, такие как реальное время (wall-clock time) или процессорное время. Передайте функцию таймера в конструктор:208209```python210pr = profiling.tracing.Profile(my_timer_function)211```212213Функция таймера должна возвращать одно число, представляющее текущее время. Если она возвращает целые числа, также укажите *timeunit*, чтобы указать продолжительность одной единицы:214215```python216# Таймер возвращает время в миллисекундах217pr = profiling.tracing.Profile(my_ms_timer, 0.001)218```219220Для наилучшей производительности функция таймера должна быть как можно быстрее. Профилировщик вызывает её часто, поэтому накладные расходы таймера напрямую влияют на накладные расходы профилирования.221222Модуль [`time`](https://python-all.ru/3.15/library/time.html#module-time) предоставляет несколько функций, подходящих для использования в качестве пользовательских таймеров:223224- [`time.perf_counter()`](https://python-all.ru/3.15/library/time.html#time.perf_counter) для астрономического времени (высокое разрешение)225- [`time.process_time()`](https://python-all.ru/3.15/library/time.html#time.process_time) для процессорного времени (без учёта сна)226- [`time.monotonic()`](https://python-all.ru/3.15/library/time.html#time.monotonic) для монотонного времени227228## Ограничения229230Детерминированное профилирование имеет внутренние ограничения, связанные с точностью измерения времени.231232Базовый таймер обычно имеет разрешение около одной миллисекунды. Измерения не могут быть точнее этого разрешения. При достаточном количестве измерений ошибки синхронизации обычно усредняются, но отдельные измерения могут быть неточными.233234Существует также задержка между моментом возникновения события и моментом захвата временной метки профилировщиком. Аналогично, после чтения временной метки есть задержка, прежде чем пользовательский код возобновит выполнение. Часто вызываемые функции накапливают эту задержку, из-за чего они могут казаться медленнее, чем на самом деле. Эта ошибка обычно составляет менее одного тика часов на вызов, но может стать значительной для функций, вызываемых многократно.235236Модуль `profiling.tracing` (и его псевдоним `cProfile`) реализован как расширение на C с низкими накладными расходами, поэтому эти проблемы синхронизации менее заметны по сравнению с устаревшим чисто Python-модулем [`profile`](https://python-all.ru/3.15/library/profile.html#module-profile).237238> **См. также**239>240> **[`profiling`](https://python-all.ru/3.15/library/profiling.html#module-profiling)**241>242> Обзор инструментов профилирования Python и рекомендации по выбору профилировщика.243>244> **[`profiling.sampling`](https://python-all.ru/3.15/library/profiling.sampling.html#module-profiling.sampling)**245>246> Статистический профилировщик с выборкой для использования в production.247>248> **[`pstats`](https://python-all.ru/3.15/library/pstats.html#module-pstats)**249>250> Анализ статистики и форматирование данных профилирования.251>252> **[`profile`](https://python-all.ru/3.15/library/profile.html#module-profile)**253>254> Устаревший чисто Python-профилировщик (включает документацию по калибровке).255