| Name | flowtrace JSON |
| Version |
0.4.1
JSON |
| download |
| home_page | None |
| Summary | System-level execution tracer for Python 3.12+ (PEP 669) |
| upload_time | 2025-11-02 14:14:57 |
| maintainer | None |
| docs_url | None |
| author | None |
| requires_python | >=3.12 |
| license | MIT |
| keywords |
python
monitoring
tracing
pep669
async
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
> 🌐 Also available in: [Русская версия](README.ru.md)
<p align="center">
<img src="https://raw.githubusercontent.com/Python-Fork/FlowTrace/main/logo.png" width="400" alt="FlowTrace logo">
</p>
# 🌀 FlowTrace — Visual Execution Tracing for Python 3.12+
[](https://pypi.org/project/flowtrace/)
[](#)
>FlowTrace is a system-level tracer built on Python’s Monitoring API (PEP 669).
>It doesn’t “profile time by default”. Instead, it reconstructs what happened in your program — calls, returns,
>structure — with minimal overhead and zero monkey-patching.
> **Status**: experimental alpha. Python 3.12+ only.
---
## Installation
```
pip install flowtrace
```
---
## Quick Start
### 1) One-line decorator
```python
from flowtrace import trace
@trace
def fib(n):
return n if n < 2 else fib(n-1) + fib(n-2)
fib(3)
```
Output:
```
→ fib(3)
→ fib(2)
→ fib(1) → 1
→ fib(0) → 0
← fib(2) → 1
→ fib(1) → 1
← fib(3) → 2
```
---
## 2) Timing when you need it
```python
from flowtrace import trace
@trace(show_timing=True)
def compute(a, b):
return a * b
compute(6, 7)
```
Output:
```
→ compute(6, 7) [0.000265s] → 42
```
---
## 3) Manual session
```python
from flowtrace import start_tracing, stop_tracing, print_tree
def fib(n):
return n if n < 2 else fib(n-1) + fib(n-2)
start_tracing()
fib(3)
events = stop_tracing()
print_tree(events)
```
Output:
```
→ fib()
→ fib()
→ fib() → 1
→ fib() → 0
← fib() → 1
→ fib() → 1
← fib() → 2
```
---
## Global configuration
```python
import flowtrace
flowtrace.config(show_args=False, show_result=True, show_timing=True)
```
Controls which information is collected globally.
All flags default to True.
| Flag | Description |
| ------------- | ------------------------------------- |
| `show_args` | capture and display call arguments |
| `show_result` | capture and display return values |
| `show_timing` | measure and display function duration |
## Function-level overrides
```python
@flowtrace.trace(show_args=True)
def foo(x): ...
```
Local flags temporarily override global ones for this function only;
child calls inherit the global configuration.
Example
```python
import flowtrace
flowtrace.config(show_args=False, show_result=True, show_timing=True)
@flowtrace.trace
def a(x): return b(x) + 1
@flowtrace.trace(show_args=True)
def b(y): return y * 2
a(10)
```
Output:
```
→ a() [0.000032s] → 21
→ b(y=10) [0.000010s] → 20
← b(y=10)
← a()
```
---
## Why FlowTrace?
- **Not a profiler**: profilers answer “how long”. FlowTrace answers “what, in which order, and why”.
- **Direct line to the VM**: listens to bytecode-level events via sys.monitoring (PEP 669).
- **No code intrusion**: no sys.settrace, no monkey-patching, no stdout noise.
---
## API (current)
```python
from flowtrace import trace, config, start_tracing, stop_tracing, get_trace_data, print_tree
```
- ```@trace(measure_time: bool = True)```
Decorate a function to include its calls in the trace.
When ```measure_time=True```, durations for this function’s calls are recorded.
- ```start_tracing()``` / ```stop_tracing() -> list[CallEvent]```
Start/stop a process-wide tracing session. By default no timing is recorded here — only structure.
- ```get_trace_data() -> list[CallEvent]```
Access the last recorded events.
- ```print_tree(events)```
Pretty-print a hierarchical call tree.
### Event model (```CallEvent```):
``` python
id: int
kind: str
func_name: str
parent_id: int | None
args_repr: str | None
result_repr: str | None
duration: float | None
collect_args: bool
collect_result: bool
collect_timing: bool
```
---
## Design choices (snapshot)
- **Only ```PY_START``` / ```PY_RETURN```**: we do not listen to ```CALL``` to keep the core lean.
Argument strings are provided by the decorator right before the call starts.
- **Exception lifecycle tracing**: FlowTrace now listens to exception-related
signals (`RAISE`, `RERAISE`, `EXCEPTION_HANDLED`, `PY_UNWIND`).
Each function frame produces at most one exception event, labeled as
`[caught]` (handled locally) or `[propagated]` (escaped outward).
- **Timing is opt-in**: ```perf_counter()``` is used only when ```measure_time=True```.
Starting/stopping a session alone does not add timing overhead.
- **Filter user code**: internal modules and site-packages are excluded from the default output.
---
## Design notes
- Zero-overhead when disabled: arguments, results, and timing are gathered only if their flags are True.
- Named argument binding: readable form like a=5, b=2 via inspect.signature, cached at decoration time.
- No cascades: per-function flags affect only that decorated function.
---
## Roadmap
- **Async/coroutine transitions.**
- **JSON export for post-processing.**
- **Include/exclude filters & colorized output.**
- **Minimal CLI helpers.**
---
## Contributing
We welcome small, surgical PRs. The codebase is intentionally compact to be an approachable learning tool for exploring Python 3.12+ internals.
## Development
```bash
python -m pip install -U pip
pip install -e . # editable install
pip install -U ruff mypy pytest pre-commit
pre-commit install
pytest -q
ruff format .
ruff check .
mypy flowtrace
Raw data
{
"_id": null,
"home_page": null,
"name": "flowtrace",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "python, monitoring, tracing, PEP669, async",
"author": null,
"author_email": "Alexandr153 <boss191105@bk.ru>",
"download_url": "https://files.pythonhosted.org/packages/5a/28/7dfb72f3766ae96e6bbb7426d8cbca40954b42a2b40be53d70f1e849d2dd/flowtrace-0.4.1.tar.gz",
"platform": null,
"description": "> \ud83c\udf10 Also available in: [\u0420\u0443\u0441\u0441\u043a\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f](README.ru.md)\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/Python-Fork/FlowTrace/main/logo.png\" width=\"400\" alt=\"FlowTrace logo\">\n</p>\n\n# \ud83c\udf00 FlowTrace \u2014 Visual Execution Tracing for Python 3.12+\n[](https://pypi.org/project/flowtrace/)\n[](#)\n\n>FlowTrace is a system-level tracer built on Python\u2019s Monitoring API (PEP 669).\n>It doesn\u2019t \u201cprofile time by default\u201d. Instead, it reconstructs what happened in your program \u2014 calls, returns,\n>structure \u2014 with minimal overhead and zero monkey-patching.\n\n> **Status**: experimental alpha. Python 3.12+ only.\n\n---\n## Installation\n```\npip install flowtrace\n```\n---\n## Quick Start\n### 1) One-line decorator\n```python\nfrom flowtrace import trace\n\n@trace\ndef fib(n):\n return n if n < 2 else fib(n-1) + fib(n-2)\n\nfib(3)\n```\n\nOutput:\n\n```\n\u2192 fib(3)\n \u2192 fib(2)\n \u2192 fib(1) \u2192 1\n \u2192 fib(0) \u2192 0\n \u2190 fib(2) \u2192 1\n \u2192 fib(1) \u2192 1\n\u2190 fib(3) \u2192 2\n```\n---\n## 2) Timing when you need it\n```python\nfrom flowtrace import trace\n\n@trace(show_timing=True)\ndef compute(a, b):\n return a * b\n\ncompute(6, 7)\n```\n\nOutput:\n\n```\n\u2192 compute(6, 7) [0.000265s] \u2192 42\n```\n---\n## 3) Manual session\n```python\nfrom flowtrace import start_tracing, stop_tracing, print_tree\n\ndef fib(n):\n return n if n < 2 else fib(n-1) + fib(n-2)\n\nstart_tracing()\nfib(3)\nevents = stop_tracing()\nprint_tree(events)\n```\n\nOutput:\n```\n\u2192 fib()\n \u2192 fib()\n \u2192 fib() \u2192 1\n \u2192 fib() \u2192 0\n \u2190 fib() \u2192 1\n \u2192 fib() \u2192 1\n\u2190 fib() \u2192 2\n```\n---\n## Global configuration\n```python\nimport flowtrace\nflowtrace.config(show_args=False, show_result=True, show_timing=True)\n```\nControls which information is collected globally.\nAll flags default to True.\n\n| Flag | Description |\n| ------------- | ------------------------------------- |\n| `show_args` | capture and display call arguments |\n| `show_result` | capture and display return values |\n| `show_timing` | measure and display function duration |\n\n## Function-level overrides\n```python\n@flowtrace.trace(show_args=True)\ndef foo(x): ...\n```\n\nLocal flags temporarily override global ones for this function only;\nchild calls inherit the global configuration.\n\nExample\n```python\nimport flowtrace\n\nflowtrace.config(show_args=False, show_result=True, show_timing=True)\n\n@flowtrace.trace\ndef a(x): return b(x) + 1\n\n@flowtrace.trace(show_args=True)\ndef b(y): return y * 2\n\na(10)\n```\nOutput:\n```\n\u2192 a() [0.000032s] \u2192 21\n \u2192 b(y=10) [0.000010s] \u2192 20\n \u2190 b(y=10)\n\u2190 a()\n```\n---\n## Why FlowTrace?\n\n- **Not a profiler**: profilers answer \u201chow long\u201d. FlowTrace answers \u201cwhat, in which order, and why\u201d.\n\n- **Direct line to the VM**: listens to bytecode-level events via sys.monitoring (PEP 669).\n\n- **No code intrusion**: no sys.settrace, no monkey-patching, no stdout noise.\n\n---\n\n## API (current)\n```python\nfrom flowtrace import trace, config, start_tracing, stop_tracing, get_trace_data, print_tree\n```\n\n- ```@trace(measure_time: bool = True)```\nDecorate a function to include its calls in the trace.\nWhen ```measure_time=True```, durations for this function\u2019s calls are recorded.\n\n- ```start_tracing()``` / ```stop_tracing() -> list[CallEvent]```\nStart/stop a process-wide tracing session. By default no timing is recorded here \u2014 only structure.\n\n- ```get_trace_data() -> list[CallEvent]```\nAccess the last recorded events.\n\n- ```print_tree(events)```\nPretty-print a hierarchical call tree.\n \n### Event model (```CallEvent```):\n``` python\nid: int\nkind: str\nfunc_name: str\nparent_id: int | None\nargs_repr: str | None\nresult_repr: str | None\nduration: float | None\ncollect_args: bool\ncollect_result: bool\ncollect_timing: bool\n```\n---\n## Design choices (snapshot)\n\n- **Only ```PY_START``` / ```PY_RETURN```**: we do not listen to ```CALL``` to keep the core lean.\nArgument strings are provided by the decorator right before the call starts.\n\n- **Exception lifecycle tracing**: FlowTrace now listens to exception-related\n signals (`RAISE`, `RERAISE`, `EXCEPTION_HANDLED`, `PY_UNWIND`).\n Each function frame produces at most one exception event, labeled as\n `[caught]` (handled locally) or `[propagated]` (escaped outward).\n\n- **Timing is opt-in**: ```perf_counter()``` is used only when ```measure_time=True```.\nStarting/stopping a session alone does not add timing overhead.\n\n- **Filter user code**: internal modules and site-packages are excluded from the default output.\n---\n## Design notes\n\n- Zero-overhead when disabled: arguments, results, and timing are gathered only if their flags are True.\n\n- Named argument binding: readable form like a=5, b=2 via inspect.signature, cached at decoration time.\n\n- No cascades: per-function flags affect only that decorated function.\n---\n## Roadmap\n\n- **Async/coroutine transitions.**\n\n- **JSON export for post-processing.**\n\n- **Include/exclude filters & colorized output.**\n\n- **Minimal CLI helpers.**\n\n---\n## Contributing\n\nWe welcome small, surgical PRs. The codebase is intentionally compact to be an approachable learning tool for exploring Python 3.12+ internals.\n\n## Development\n\n```bash\npython -m pip install -U pip\npip install -e . # editable install\npip install -U ruff mypy pytest pre-commit\npre-commit install\npytest -q\nruff format .\nruff check .\nmypy flowtrace\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "System-level execution tracer for Python 3.12+ (PEP 669)",
"version": "0.4.1",
"project_urls": {
"Documentation": "https://github.com/Python-Fork/FlowTrace/blob/main/README.md",
"Homepage": "https://github.com/Python-Fork/FlowTrace",
"Issues": "https://github.com/Python-Fork/FlowTrace/issues"
},
"split_keywords": [
"python",
" monitoring",
" tracing",
" pep669",
" async"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "63d5508f3fdf2261973a47e463ed84cbd0acbb56c237e2320db10224c28ba721",
"md5": "2251ac17f552fff44065d402d79f7e6d",
"sha256": "4da71eb78d113c5187a93da942aeb4514203ded71bb118ce2b6ff3d333d33a3f"
},
"downloads": -1,
"filename": "flowtrace-0.4.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "2251ac17f552fff44065d402d79f7e6d",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 14090,
"upload_time": "2025-11-02T14:14:56",
"upload_time_iso_8601": "2025-11-02T14:14:56.345766Z",
"url": "https://files.pythonhosted.org/packages/63/d5/508f3fdf2261973a47e463ed84cbd0acbb56c237e2320db10224c28ba721/flowtrace-0.4.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "5a287dfb72f3766ae96e6bbb7426d8cbca40954b42a2b40be53d70f1e849d2dd",
"md5": "9ba05ca2c7a4c15207ef3a3928dfcbce",
"sha256": "237206860b48c3cb87fa71b9a25d855674d7c6f03296a6e8d47f58a2f0a99202"
},
"downloads": -1,
"filename": "flowtrace-0.4.1.tar.gz",
"has_sig": false,
"md5_digest": "9ba05ca2c7a4c15207ef3a3928dfcbce",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 16532,
"upload_time": "2025-11-02T14:14:57",
"upload_time_iso_8601": "2025-11-02T14:14:57.378617Z",
"url": "https://files.pythonhosted.org/packages/5a/28/7dfb72f3766ae96e6bbb7426d8cbca40954b42a2b40be53d70f1e849d2dd/flowtrace-0.4.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-11-02 14:14:57",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Python-Fork",
"github_project": "FlowTrace",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "flowtrace"
}