Pyinstrument
🚴 Call stack profiler for Python. Shows you why your code is slow!
Install / Use
/learn @joerick/PyinstrumentREADME
pyinstrument
<!-- MARK intro start -->Pyinstrument is a Python profiler. A profiler is a tool to help you optimize your code - make it faster. To get the biggest speed increase you should focus on the slowest part of your program. Pyinstrument helps you find it!
<!-- MARK intro end -->☕️ Not sure where to start? Check out this video tutorial from calmcode.io!
Installation
<!-- MARK installation start -->pip install pyinstrument
Pyinstrument supports Python 3.8+.
<!-- MARK installation end -->To run Pyinstrument from a git checkout, there's a build step. Take a look at Contributing for more info.
Documentation
To learn how to use pyinstrument, or to check the reference, head to the documentation.
Known issues
- Profiling code inside a Docker container can cause some strange results, because the gettimeofday syscall that pyinstrument uses is slow in that environment. See #83
- When using
pyinstrument script.pywherescript.pycontains a class serialized withpickle, you might encounter errors because the serialisation machinery doesn't know where__main__is. See this issue for workarounds
Changelog
v5.1.2
4 January 2026
- Adds the ability to customize description using CLI option
--target-description(#408) - You can set the interval for the Django middleware using the PYINSTRUMENT_INTERVAL option (#416)
- HTMLRenderer can now run preprocessors on the input, to manipulate the call tree before writing to HTML (#403)
- Fix a bug where mismatched start/stops can produce "call stack without an active session" errors (#406)
- Limit sample count for the HTML renderer to ensure the browser can load the sample (#407)
v5.1.1
12 August 2025
- Fix some memory leaks in the low-level C extension (#394)
v5.1.0
10 August 2025
- Precision of printed durations now adapts to the interval of the profile. This allows you to see more detail when the interval, and hides unnecessary detail when the interval is large. (#390)
- Adds an option to the Django middleware to customise the filename of saved profile runs using a callback (#393)
- Adds an aiohttp.web example to the documentation (#389)
v5.0.3
2 July 2025
- Fix a bug where the HTML renderer would crash when the profile is empty (#377)
v5.0.2
24 May 2025
- Fix a bug that caused jupyter notebooks to continue to run after a profiled cell was interrupted with Ctrl-C (#373)
- Fix a type annotation issue when using mypy and import pyinstrument (#373)
v5.0.1
23 January 2025
- Adds a Django option to customise the filename of saved profile runs (#339)
- Improve the FastAPI integration docs (#355)
- Include more options in the IPython magic (#350)
v5.0.0
11 October 2024
Loads of improvements to the HTML renderer!
-
Timeline mode - see and zoom into an interactive linear timeline!

-
HTML mode now has interactive options, rather than needing to set the upfront.
-
Streamlined the design of the HTML page header.
-
HTML Call stack view supports arrow key navigation.
-
The way ‘library’ code is detected has been changed. Previously, if the string ‘/lib/’ occurred in the file path, that was considered library code (and collapsed by default). Now, pyinstrument captures the paths of the Python install and any active virtualenv/conda env at profile time. Files that are stored there are considered library. That should give fewer false positives.
-
Calls to profiler.start() can now pass a target_description parameter, which is displayed in the profile readout.
Check my blog post for more info on the new features.
v4.7.3
6 September 2024
- Fix a bug introduced in 4.7.0 which would cause the profiler to crash when profiling code with unusual locals, notably some pytest extensions (#332)
- Fix a bug that causes pyinstrument to fail to import packages like
glomon Python 3.12 or later, which mutate the locals() dict. (#336) - Fix a bug that caused a
UnicodeDecodeErroron some platforms (#330) - Fix a DivideByZero error that occurs in some situations
- The IPython integration takes greater step to ensure a clean profile output, by ensuring internal frames are trimmed before printing. (#321)
v4.7.2
5 August 2024
- Add CPython 3.13 wheels
- Fix a bug that caused the HTML output to fail to render in some browser contexts (#328)
v4.7.1
2 August 2024
- Fix issue with PyPI upload
v4.7.0
1 August 2024
- Adds a new, convenient API for profiling chunks of Python code! You can now profile simply using a
withblock, or a function/method decorator. This will profile the code and print a short readout into the terminal. (#327) - Adds new, lower overhead timing options. Pyinstrument calls timers on every Python function call, which is fine on systems with fast timing available, but it adds significant overhead on systems that require a syscall for each, such as some Docker environments. Pyinstrument will now detect slow timers present a warning with two choices. You can enable a 'timing thread', which offloads the timing workload from the profiled thread, or, if you're happy with lower resolution, you can opt to use a 'coarse' timer, which is provided on some Linux systems. (#273)
- Alt-click rows in the HTML output to collapse/expand the whole tree (#325)
- Adds a
flatargument to the console output, to present a flat list of functions (#294) - Adds a Litestar example config and docs (#284)
- Preliminary Python 3.13 support (#322)
v4.6.2
26 January 2024
- Fixes a bug with the pstats renderer, where additional frames could be seen in the output. (#287)
- Adds
show_alloption to Profiler.output_html
v4.6.1
8 November 2023
- Fixes a bug with unwanted variable expansion in the IPython magics
%pyinstrument(#278)
v4.6.0
12 October 2023
- Adds a feature
-c, which allows profiling code directly from the command line, likepython -c. (#271) - Adds a convenience method
Profiler.write_html, for writing HTML output to a file directly. (#266)
v4.5.3
7 September 2023
- Fix a problem in the packaging process that prevented upload to PyPI
v4.5.2
1 September 2023
- Show the program name in the header of the HTML output (#260)
- Improve program name capture through resilience to other programs modifying sys.argv (#258)
- Add support for Python 3.12 (#246)
v4.5.1
22 July 2023
- Fix a bug that caused
[X frames hidden]in the output when frames were deleted due to__tracebackhide__(#255) - Fix a bug causing built-in code to display the filepath
Nonein the console output (#254) - Some docs improvements (#251)
v4.5.0
5 June 2023
- Adds a flat mode to the console renderer, which can be enabled by passing
-p flaton the command line. This mode shows the heaviest frame as measured by self-time, which can be useful in some codebases. (#240) - Adds the ability to save
pstatsfiles. This is the file format used by cprofile in the stdlib. It's less detailed than pyinstrument profiles, but it's compatible with more tools. (#236) - Fixes a detail of the
--show-alloption - pyinstrument will no longer remove Python-internal frames when this option is supplied. (#239) - Internally to the HTML renderer, it now uses Svelte to render the frontend, meaning profile HTML files bundle less javascript and so are smaller. (#222)
v4.4.0
5 November 2022
- Adds the class name to methods in the console & HTML outputs (#203)
- Fix a bug that caused pyinstrument machinery to appear at the start of a profile (#215)
- Frames that set a
__traceback_hide__local variable will now be removed from the output (#217) - Jupyter/IPython magic now supports async/await, if you run with a
--async_mode=enabledflag. (#212) - Fix a crash when more than one root frame is captured in a thread - this can happen with gevent.
- A big refactor to the backend, allowing more than just static information to be captured. This currently is just powering the class name feature, but more is to come!
v4.3.0
21 August 2022
- Adds buttons in the HTML output to switch between absolute and proportional (percentage) time.
- Adds a command line flag
--interval(seconds, default 0.001) to change the interval that pyinstrument samples a program. This is useful for long-running programs, where increasing the interval reduces the memory overhead. - Includes wheels for CPython 3.11.
v4.2.0
- Adds a command-line option
-p

