Registry / observability / pyccolo

pyccolo

JSON →
library0.0.86pypypi✓ verified 88d ago

Pyccolo (pronounced like "piccolo") is a library for declarative instrumentation in Python, allowing users to specify *what* instrumentation to perform rather than *how* to implement it. It aims for ergonomics, composability, and portability across various Python versions. It achieves this by embedding instrumentation at the source code level. The library is actively maintained, with the current version being 0.0.85, and supports Python versions from 3.6 up to 3.14 (since v0.0.73).

pip install pyccolo
INSTALL
IMPORT
SIG · PYCCOLO
P
pyccolo
observabilitypythonv0.0.86
Install
1.8s avg
Import
186ms
Disk
18MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.9–3.13
musl
3.9–3.13
Install & Compatibility
Where this runs
tested against v0.0.86 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.10–3.910 runs
installs and imports cleanly · install 0.0s · import 0.192s · 19.6MB
glibc
py 3.10–3.910 runs
installs and imports cleanly · install 1.8s · import 0.180s · 20MB
18MB installed
● package 18MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

BaseTracer
✓ from pyccolo import BaseTracer
Commonly imported as `pyc.BaseTracer` after `import pyccolo as pyc`.
before_stmt
✓ from pyccolo import before_stmt
Commonly imported as `pyc.before_stmt` for event handlers.
Null
✓ from pyccolo import Null
Used for explicitly overriding values with None in handlers.

This quickstart demonstrates how to create a custom tracer that logs statements before execution. It highlights the use of `BaseTracer` and the `should_instrument_file` method to control which files are instrumented, as well as a `before_stmt` event handler.

import pyccolo as pyc class MyTracer(pyc.BaseTracer): def should_instrument_file(self, filename: str) -> bool: # Only instrument files ending with 'my_script.py' # For broader instrumentation, adjust this logic. return 'my_script.py' in filename @pyc.before_stmt def on_before_statement(self, ret, node, frame, event): print(f"Executing statement: {node.lineno}: {node.__class__.__name__}") # Example usage with a dummy script content script_content = """ print("Hello from my_script.py") x = 1 + 2 if x == 3: print("x is 3") """ # To simulate a file, we can use exec with a custom globals dict # and then trace its execution within a temporary module scope. import types import sys # Create a dummy module to hold our script content, so should_instrument_file can identify it my_script_module = types.ModuleType('my_script') my_script_module.__file__ = '<string>my_script.py' sys.modules['my_script'] = my_script_module # Execute the script content within the dummy module's namespace with MyTracer(): exec(script_content, my_script_module.__dict__) # Clean up the dummy module del sys.modules['my_script']
Debug
Known issues
gotchaPyccolo's instrumentation for imported modules is opt-in, not automatic. If you expect a module imported within a tracing context to be instrumented, you must explicitly enable it.
fix
Subclass `pyccolo.BaseTracer` and override the `should_instrument_file(self, filename: str) -> bool` method to return `True` for the desired module filenames.
affects: All versions
gotchaWhen using handlers that can override expression return values (e.g., `before_attribute_load`), returning `None` means 'no override'. If you intend to explicitly override a value with `None`, you must return `pyccolo.Null`.
fix
Use `return pyccolo.Null` if you want to set the overridden value to `None`. Otherwise, `return None` will cause the original expression's value to be used.
affects: All versions
gotchaAdvanced syntax augmentation features, such as optional chaining (`?.`), are only supported on Python 3.8 and newer. Using them on older Python versions or without the specific tracer enabled will result in a `SyntaxError`.
fix
Ensure your project is running on Python 3.8 or newer when using syntax augmentation. Also, activate the correct tracer (e.g., `pyccolo.examples.OptionalChainer`) that implements the desired syntax transformation.
affects: <3.8
gotchaWhile Pyccolo is designed to be composable with existing `sys.settrace` functions, complex interactions can still occur. If you observe unexpected behavior with other tracing tools, it might be due to subtle conflicts.
fix
Pyccolo aims to execute both its handlers and any active `sys.settrace` functions. If conflicts arise, simplify your tracing setup to isolate the issue, and consult Pyccolo's documentation or examples (e.g., how it co-exists with `coverage.py`).
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'pyccolo'
The `pyccolo` library has not been installed or is not accessible in the current Python environment.
fix
Run `pip install pyccolo` in your terminal to install the library.
TypeError: 'NoneType' object is not callable (or similar error related to uninstrumented code)
An imported module or file was expected to be instrumented by a `pyccolo` tracer, but its code was executed without the tracer's handlers being applied.
fix
Ensure your custom `BaseTracer` implementation's `should_instrument_file` method correctly identifies and allows the target file(s) to be instrumented. Remember that instrumentation is opt-in for imports.
SyntaxError: invalid syntax (when using optional chaining '?.')
Attempting to use new Python syntax features (like the optional chaining `?.`) that are either not supported by your Python version or require a specific `pyccolo` syntax augmentation tracer that isn't active.
fix
Verify that your Python interpreter is version 3.8 or higher. If the syntax is a `pyccolo` augmentation, ensure the corresponding tracer (e.g., `pyccolo.examples.OptionalChainer`) is activated.
Unexpected expression value after handler execution (handler appeared to do nothing)
A handler was intended to override an expression's return value with `None`, but it implicitly returned `None` causing the original value to be used instead.
fix
If the intention is to explicitly set the expression's value to `None` from a handler, return `pyccolo.Null` instead of `None`.
Upgrade
Version history
0.0.86latest on PyPI · released Jun 13, 2026
Audit
Dependencies

No dependency data recorded yet.

Agent activity
24 hits · last 30 days
node
18
OpenAI (training)
2
Resources
pyccolo — pip install pyccolo · libregistry