Skip to content
Back to top
View this page

# API Reference

## Command line interface

`pyinstrument` works just like `python`, on the command line, so you can call your scripts like `pyinstrument script.py` or `pyinstrument -m my_module`.

When your script ends, or when you kill it with `ctrl-c`, pyinstrument will print a profile report to the console.

    Usage: pyinstrument [options] scriptfile [arg] ...

    Options:
      --version             show program's version number and exit
      -h, --help            show this help message and exit
      --load=FILENAME       instead of running a script, load a profile session
                            from a pyisession file
      --load-prev=IDENTIFIER
                            instead of running a script, load a previous profile
                            session as specified by an identifier
      -m MODULE             run library module as a script, like 'python -m
                            module'
      -c PROGRAM            program passed in as string, like 'python -c "..."'
      --from-path           (POSIX only) instead of the working directory, look
                            for scriptfile in the PATH environment variable
      -o OUTFILE, --outfile=OUTFILE
                            save to <outfile>
      -r RENDERER, --renderer=RENDERER
                            how the report should be rendered. One of: 'text',
                            'html', 'json', 'speedscope', 'pyisession', 'pstats',
                            or python import path to a renderer class. Defaults to
                            the appropriate format for the extension if OUTFILE is
                            given, otherwise, defaults to 'text'.
      -p RENDER_OPTION, --render-option=RENDER_OPTION
                            options to pass to the renderer, in the format
                            'flag_name' or 'option_name=option_value'. For
                            example, to set the option 'time', pass '-p
                            time=percent_of_total'. To pass multiple options, use
                            the -p option multiple times. You can set processor
                            options using dot-syntax, like '-p
                            processor_options.filter_threshold=0'. option_value is
                            parsed as a JSON value or a string.
      -t, --timeline        render as a timeline - preserve ordering and don't
                            condense repeated calls
      --target-description=TARGET_DESCRIPTION
                            description text to display in the report. The
                            placeholder '{args}' may be used to include the CLI
                            arguments passed to the target script, including the
                            script name. Default: 'Program: {args}'
      --hide=EXPR           glob-style pattern matching the file paths whose
                            frames to hide. Defaults to hiding non-application
                            code
      --hide-regex=REGEX    regex matching the file paths whose frames to hide.
                            Useful if --hide doesn't give enough control.
      --show=EXPR           glob-style pattern matching the file paths whose
                            frames to show, regardless of --hide or --hide-regex.
                            For example, use --show '*/<library>/*' to show frames
                            within a library that would otherwise be hidden.
      --show-regex=REGEX    regex matching the file paths whose frames to always
                            show. Useful if --show doesn't give enough control.
      --show-all            show everything
      --unicode             (text renderer only) force unicode text output
      --no-unicode          (text renderer only) force ascii text output
      --color               (text renderer only) force ansi color text output
      --no-color            (text renderer only) force no color text output
      -i INTERVAL, --interval=INTERVAL
                            Minimum time, in seconds, between each stack sample.
                            Smaller values allow resolving shorter duration
                            function calls but incur a greater runtime and memory
                            consumption overhead. For longer running scripts,
                            setting a larger interval reduces the memory
                            consumption required to store the stack samples.
      --use-timing-thread   Use a separate thread to time the interval between
                            stack samples. This can reduce the overhead of
                            sampling on some systems.

## Python API

The Python API is also available, for calling pyinstrument directly from Python and writing integrations with with other tools.

### The `profile` function

For example:

    with pyinstrument.profile():
        time.sleep(1)

This will print something like:

    pyinstrument ........................................
    .
    .  Block at testfile.py:2
    .
    .  1.000 <module>  testfile.py:1
    .  └─ 1.000 sleep  <built-in>
    .
    .....................................................

You can also use it as a function/method decorator, like this:

    @pyinstrument.profile()
    def my_function():
        time.sleep(1)

pyinstrument.profile(*, interval=0.001, async_mode='disabled', use_timing_thread=None, renderer=None, target_description=None)

  Creates a context-manager or function decorator object, which profiles the given code and prints the output to stdout.

  The interval, async_mode and use_timing_thread parameters are passed through to the underlying `pyinstrument.Profiler` object.

  You can pass a renderer to customise the output. By default, it uses a `ConsoleRenderer` with short_mode set.

### The Profiler object

class pyinstrument.Profiler(interval=0.001, async_mode='enabled', use_timing_thread=None)

  The profiler - this is the main way to use pyinstrument.

  Note the profiling will not start until `start()` is called.

  Parameters:

    - interval (float) – See `interval`.

    - async_mode (AsyncMode) – See `async_mode`.

    - use_timing_thread (bool | None) – If True, the profiler will use a separate thread to keep track of time. This is useful if you’re on a system where getting the time has significant overhead.

  property interval: float

    The minimum time, in seconds, between each stack sample. This translates into the resolution of the sampling.

  property async_mode: str

    Configures how this Profiler tracks time in a program that uses async/await.

    `enabled`

      When this profiler sees an `await`, time is logged in the function that awaited, rather than observing other coroutines or the event loop.

    `disabled`

      This profiler doesn’t attempt to track `await`. In a program that uses async/await, this will interleave other coroutines and event loop machinery in the profile. Use this option if async support is causing issues in your use case, or if you want to run multiple profilers at once.

    `strict`

      Instructs the profiler to only profile the current async context. Frames that are observed in another context are ignored, tracked instead as `<out-of-context>`.

  property last_session: Session | None

    The previous session recorded by the Profiler.

  start(caller_frame=None, target_description=None)

    Instructs the profiler to start - to begin observing the program’s execution and recording frames.

    The normal way to invoke `start()` is with a new instance, but you can restart a Profiler that was previously running, too. The sessions are combined.

    Parameters:

      caller_frame (FrameType | None) –

      Set this to override the default behaviour of treating the caller of `start()` as the ‘start_call_stack’ - the instigator of the profile. Most renderers will trim the ‘root’ from the call stack up to this frame, to present a simpler output.

      You might want to set this to `inspect.currentframe().f_back` if you are writing a library that wraps pyinstrument.

  stop()

    Stops the profiler observing, and sets `last_session` to the captured session.

    Returns:

      The captured session.

    Return type:

      Session

  property is_running

    Returns True if this profiler is running - i.e. observing the program execution.

  reset()

    Resets the Profiler, clearing the last_session.

  __enter__()

    Context manager support.

    Profilers can be used in with blocks! See this example:

        with Profiler() as p:
            # your code here...
            do_some_work()

        # profiling has ended. let's print the output.
        p.print()

  print(file=sys.stdout, *, unicode=None, color=None, show_all=False, timeline=False, time='seconds', flat=False, flat_time='self', short_mode=False, processor_options=None)

    Print the captured profile to the console, as rendered by `renderers.ConsoleRenderer`

    Parameters:

      file (IO[str]) – the IO stream to write to. Could be a file descriptor or sys.stdout, sys.stderr. Defaults to sys.stdout.

    See `renderers.ConsoleRenderer` for the other parameters.

  output_text(unicode=False, color=False, show_all=False, timeline=False, time='seconds', flat=False, flat_time='self', short_mode=False, processor_options=None)

    Return the profile output as text, as rendered by `ConsoleRenderer`

    See `renderers.ConsoleRenderer` for parameter description.

  output_html(resample_interval=None)

    Return the profile output as HTML, as rendered by `HTMLRenderer`

    See `renderers.HTMLRenderer` for parameter description.

  write_html(path, timeline=False, show_all=False, resample_interval=None)

    Writes the profile output as HTML to a file, as rendered by `HTMLRenderer`

  open_in_browser(timeline=False, resample_interval=None)

    Opens the last profile session in your web browser.

  output(renderer)

    Returns the last profile session, as rendered by `renderer`.

    Parameters:

      renderer (Renderer) – The renderer to use.

### Sessions

class pyinstrument.session.Session

  Represents a profile session, contains the data collected during a profile session.

  static load(filename)

    Load a previously saved session from disk.

    Parameters:

      filename (str | PathLike[str]) – The path to load from.

    Return type:

      Session

  save(filename)

    Saves a Session object to disk, in a JSON format.

    Parameters:

      filename (str | PathLike[str]) – The path to save to. Using the `.pyisession` extension is recommended.

  static combine(session1, session2)

    Combines two `Session` objects.

    Sessions that are joined in this way probably shouldn’t be interpreted as timelines, because the samples are simply concatenated. But aggregate views (the default) of this data will work.

    Return type:

      Session

  root_frame(trim_stem=True)

    Parses the internal frame records and returns a tree of `Frame` objects. This object can be rendered using a `Renderer` object.

    Return type:

      A `Frame` object, or None if the session is empty.

  shorten_path(path)

    Shorten a path to a more readable form, relative to sys_path. Used by Frame.short_file_path.

  resample(interval)

    Returns a new Session object with frame records resampled to the given interval.

    Parameters:

      interval (float) – The desired sampling interval in seconds.

    Return type:

      Session

### Renderers

Renderers transform a tree of `Frame` objects into some form of output.

Rendering has two steps:

1. First, the renderer will ‘preprocess’ the Frame tree, applying each processor in the `processor` property, in turn.

2. The resulting tree is rendered into the desired format.

Therefore, rendering can be customised by changing the `processors` property. For example, you can disable time-aggregation (making the profile into a timeline) by removing `aggregate_repeated_calls()`.

class pyinstrument.renderers.FrameRenderer(show_all=False, timeline=False, processor_options=None)

  An abstract base class for renderers that process Frame objects using processor functions. Provides a common interface to manipulate the processors before rendering.

  Parameters:

    - show_all (bool) – Don’t hide or filter frames - show everything that pyinstrument captures.

    - timeline (bool) – Instead of aggregating time, leave the samples in chronological order.

    - processor_options (dict[str, Any]) – A dictionary of processor options.

  processors: List[Callable[[...], Frame | None]]

    Processors installed on this renderer. This property is defined on the base class to provide a common way for users to add and manipulate them before calling `render()`.

  processor_options: dict[str, Any]

    Dictionary containing processor options, passed to each processor.

  default_processors()

    Return a list of processors that this renderer uses by default.

  render(session)

    Return a string that contains the rendered form of frame.

class pyinstrument.renderers.ConsoleRenderer(show_all=False, timeline=False, processor_options=None, unicode=False, color=False, flat=False, time='seconds', flat_time='self', short_mode=False)

  Produces text-based output, suitable for text files or ANSI-compatible consoles.

  Parameters:

    - unicode (bool) – Use unicode, like box-drawing characters in the output.

    - color (bool) – Enable color support, using ANSI color sequences.

    - flat (bool) – Display a flat profile instead of a call graph.

    - time (LiteralStr['seconds', 'percent_of_total']) – How to display the duration of each frame - `'seconds'` or `'percent_of_total'`

    - flat_time (FlatTimeMode) – Show `'self'` time or `'total'` time (including children) in flat profile.

    - short_mode (bool) – Display a short version of the output.

    - show_all (bool) – See `FrameRenderer`.

    - timeline (bool) – See `FrameRenderer`.

    - processor_options (dict[str, Any]) – See `FrameRenderer`.

class pyinstrument.renderers.HTMLRenderer

  Renders a rich, interactive web page, as a string of HTML.

  Parameters:

    resample_interval (float | None) – Controls how the renderer deals with very large sessions. The typically struggles with sessions of more than 100,000 samples. If the session has more samples than this number, it will be automatically resampled to a coarser interval. You can control this interval with this parameter. If None (the default), the interval will be chosen automatically. Setting this to 0 disables resampling.

  preprocessors: List[Callable[[...], Frame | None]]

    Preprocessors installed on this renderer. This property is similar to `FrameRenderer.processors`, but all pyinstrument’s processing is done in the webapp, so these are only used to modify the JSON data sent to the webapp. For example, you might want to use preprocessors to remove unneeded frames from the data to reduce the size of the HTML file.

  preprocessor_options: dict[str, Any]

    Options to pass to the preprocessors, like `FrameRenderer.processor_options`.

class pyinstrument.renderers.JSONRenderer(**kwargs)

  Outputs a tree of JSON, containing processed frames.

  Parameters:

    - show_all – Don’t hide or filter frames - show everything that pyinstrument captures.

    - timeline – Instead of aggregating time, leave the samples in chronological order.

    - processor_options – A dictionary of processor options.

class pyinstrument.renderers.SpeedscopeRenderer(**kwargs)

  Outputs a tree of JSON conforming to the speedscope schema documented at

  wiki: https://github.com/jlfwong/speedscope/wiki/Importing-from-custom-sources schema: https://www.speedscope.app/file-format-schema.json spec: https://github.com/jlfwong/speedscope/blob/main/src/lib/file-format-spec.ts example: https://github.com/jlfwong/speedscope/blob/main/sample/profiles/speedscope/0.0.1/simple.speedscope.json

  Parameters:

    - show_all – Don’t hide or filter frames - show everything that pyinstrument captures.

    - timeline – Instead of aggregating time, leave the samples in chronological order.

    - processor_options – A dictionary of processor options.

### Processors

Processors are functions that take a Frame object, and mutate the tree to perform some task.

They can mutate the tree in-place, but also can change the root frame, they should always be called like:

    frame = processor(frame, options=...)

pyinstrument.processors.remove_importlib(frame, options)

  Removes `<frozen importlib._bootstrap` frames that clutter the output.

pyinstrument.processors.remove_tracebackhide(frame, options)

  Removes frames that have set a local __tracebackhide__ (e.g. __tracebackhide__ = True), to hide them from the output.

pyinstrument.processors.aggregate_repeated_calls(frame, options)

  Converts a timeline into a time-aggregate summary.

  Adds together calls along the same call stack, so that repeated calls appear as the same frame. Removes time-linearity - frames are sorted according to total time spent.

  Useful for outputs that display a summary of execution (e.g. text and html outputs)

pyinstrument.processors.group_library_frames_processor(frame, options)

  Groups frames that should be hidden into `FrameGroup` objects, according to `hide_regex` and `show_regex` in the options dict, as applied to the file path of the source code of the frame. If both match, ‘show’ has precedence. Options:

  `hide_regex`

    regular expression, which if matches the file path, hides the frame in a frame group.

  `show_regex`

    regular expression, which if matches the file path, ensures the frame is not hidden

  Single frames are not grouped, there must be at least two frames in a group.

pyinstrument.processors.merge_consecutive_self_time(frame, options, recursive=True)

  Combines consecutive ‘self time’ frames.

pyinstrument.processors.remove_unnecessary_self_time_nodes(frame, options)

  When a frame has only one child, and that is a self-time frame, remove that node and move the time to parent, since it’s unnecessary - it clutters the output and offers no additional information.

pyinstrument.processors.remove_irrelevant_nodes(frame, options, total_time=None)

  Remove nodes that represent less than e.g. 1% of the output. Options:

  `filter_threshold`

    sets the minimum duration of a frame to be included in the output. Default: 0.01.

pyinstrument.processors.remove_first_pyinstrument_frames_processor(frame, options)

  The first few frames when using the command line are the __main__ of pyinstrument, the eval, and the ‘runpy’ module. I want to remove that from the output.

### Internals notes

Frames are recorded by the Profiler in a time-linear fashion. While profiling, the profiler builds a list of frame stacks, with the frames having in format:

    function_name <null> filename <null> function_line_number

When profiling is complete, this list is turned into a tree structure of Frame objects. This tree contains all the information as gathered by the profiler, suitable for a flame render.

#### Frame objects, the call tree, and processors

The frames are assembled to a call tree by the profiler session. The time-linearity is retained at this stage.

Before rendering, the call tree is then fed through a sequence of ‘processors’ to transform the tree for output.

The most interesting is `aggregate_repeated_calls`, which combines different instances of function calls into the same frame. This is intuitive as a summary of where time was spent during execution.

The rest of the processors focus on removing or hiding irrelevant Frames from the output.

#### Self time frames vs. frame.self_time

Self time nodes exist to record time spent in a node, but not in its children. But normal frame objects can have self_time too. Why? frame.self_time is used to store the self_time of any nodes that were removed during processing.