SyncronousTracer / SynchronousTracer

The synchronous tracer installs sys.settrace and processes each event as it arrives on the calling thread. It is the default.

class pycallgraph.tracer.SyncronousTracer(outputs, config)[source]
memory()[source]

Return the current memory usage in bytes, or None if disabled.

A negative reading from memory_usage means “could not measure” (for example ps v on macOS has no RSS column). That is reported as None so it is not published as a real, negative figure, and the reason is logged once rather than on every traced event.

Both spellings resolve to the same class. The historical names misspell “Synchronous” and “Asynchronous”, but they are part of the public API, so the correctly spelled names (SynchronousTracer and AsynchronousTracer) are provided as aliases rather than a rename.

AsyncronousTracer / AsynchronousTracer

The asynchronous tracer hands every event to a TraceProcessor worker thread over a queue, so the traced program is not slowed down by the work of recording. It is enabled with Config(threaded=True) or --threaded.

Shutdown is bounded: done() waits for the queue to drain and then joins the worker with a timeout. If the worker does not finish in time, a PyCallGraphException is raised rather than blocking the traced program indefinitely.

class pycallgraph.tracer.AsyncronousTracer(outputs, config)[source]
shutdown_timeout = 10.0

How long to wait for the trace processor to drain and exit. A stuck processor used to block the traced program forever with no diagnostics.

TraceProcessor

The processor accumulates the statistics the outputs render, and is also a threading.Thread for the asynchronous case.

class pycallgraph.tracer.TraceProcessor(outputs, config)[source]

Contains a callback used by sys.settrace, which collects information about function call count, time taken, etc.

done()[source]

Ask the processor to finish and exit.

Everything already queued is still processed, then the worker exits on the sentinel. This replaces a busy-wait on queue.empty() that spun forever if the worker had already stopped.

init_libpath()[source]

Work out the directories which contain library (non-user) code.

sysconfig reports the logical install location, which is often a symlink (Homebrew, asdf and conda all do this). Modules report their real path via __file__, so both the logical and the resolved paths are recorded to keep detection working on symlinked installs.

is_module_stdlib(file_name)[source]

Returns True if file_name lives under a known library directory.

“Library” here means the standard library and installed packages: sysconfig’s stdlib/platstdlib plus the purelib/platlib (site-packages) directories. That mirrors the --stdlib option, which controls whether both are included in the trace.

The check is a path-boundary prefix match on the symlink-resolved, lower-cased path, so it is tolerant of symlinked interpreters (Homebrew, asdf, conda) and of case differences between the recorded paths and a module’s __file__.

process(frame, event, arg, memory=None)[source]

This function processes a trace result. Keeps track of relationships between calls.

run()[source]

Method representing the thread’s activity.

You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.