Follow
Follow is a flexible Python decorator that lets you trace, inspect, and log exactly what happens inside your Python code — line by line
Use it to debug, audit, or understand your code’s behavior in real time
Features
- Trace every executed line of a decorated function
- Log local variables, line content, and time spent between lines
- Selectively tracing (FollowConfig)
- Custom follower — Send trace data to print, a logger, or your own collector
- Supports multithreaded tracing with automatic worker wrapping
Installation
You can install this package via PIP: pip install python-follow
Usage
from follow import follow, FollowConfig
# Define your config
config = FollowConfig(
follow_threads=True,
follow_for_loops=True,
follow_variable_set=True,
follow_prints=True,
)
# Decorate your function
@follow(config=config)
def my_function():
a = 1
for i in range(3):
b = a + i
my_function()
# Output:
# {'function': 'my_function', 'instruction': 'a = 1', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}]}
# {'function': 'my_function', 'instruction': 'for i in range(3):', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 0, 'type': 'int'}]}
# {'function': 'my_function', 'instruction': 'b = a + i', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 0, 'type': 'int'}, {'var': 'b', 'val': 1, 'type': 'int'}]}
# {'function': 'my_function', 'instruction': 'for i in range(3):', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 1, 'type': 'int'}, {'var': 'b', 'val': 1, 'type': 'int'}]}
# {'function': 'my_function', 'instruction': 'b = a + i', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 1, 'type': 'int'}, {'var': 'b', 'val': 2, 'type': 'int'}]}
# {'function': 'my_function', 'instruction': 'for i in range(3):', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 2, 'type': 'int'}, {'var': 'b', 'val': 2, 'type': 'int'}]}
# {'function': 'my_function', 'instruction': 'b = a + i', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 2, 'type': 'int'}, {'var': 'b', 'val': 3, 'type': 'int'}]}
# {'function': 'my_function', 'instruction': 'for i in range(3):', 'execution_time': 0.0, 'local_vars': []}
Usage - Custom Collector
from follow import follow, FollowConfig
class CustomCollector:
def __init__(self):
self.traces = []
def collect(self, data: dict):
self.traces.append(data)
custom_collector = CustomCollector()
# Decorate your function
@follow(follower=custom_collector.collect)
def my_function():
a = 1
for i in range(3):
b = a + i
my_function()
# Output:
# [
# {'function': 'my_function', 'instruction': 'a = 1', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}]},
# {'function': 'my_function', 'instruction': 'for i in range(3):', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 0, 'type': 'int'}]},
# {'function': 'my_function', 'instruction': 'b = a + i', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 0, 'type': 'int'}, {'var': 'b', 'val': 1, 'type': 'int'}]},
# {'function': 'my_function', 'instruction': 'for i in range(3):', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 1, 'type': 'int'}, {'var': 'b', 'val': 1, 'type': 'int'}]},
# {'function': 'my_function', 'instruction': 'b = a + i', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 1, 'type': 'int'}, {'var': 'b', 'val': 2, 'type': 'int'}]},
# {'function': 'my_function', 'instruction': 'for i in range(3):', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 2, 'type': 'int'}, {'var': 'b', 'val': 2, 'type': 'int'}]},
# {'function': 'my_function', 'instruction': 'b = a + i', 'execution_time': 0.0, 'local_vars': [{'var': 'a', 'val': 1, 'type': 'int'}, {'var': 'i', 'val': 2, 'type': 'int'}, {'var': 'b', 'val': 3, 'type': 'int'}]},
# {'function': 'my_function', 'instruction': 'for i in range(3):', 'execution_time': 0.0, 'local_vars': []}
# ]
print(custom_collector.traces)
Metadata
Release files for python-follow 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| python_follow-0.1.2.tar.gz | 4.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| python_follow-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 8.7 kB
Release files / python_follow-0.1.2.tar.gz
| Download URL | python_follow-0.1.2.tar.gz |
|---|---|
| Size | 4.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7ee7b8d45fdc05ca3050e4ba6e590d8a1c1ef96a4eaf3263edcc822fd0f197c7
|
|
BLAKE2b-256 checksum How to use checksums |
c79a9692c0913902b08005ebd4c91e32d1eef647b091ac70eaf533b71e18ac2c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.6
|
Release files / python_follow-0.1.2-py3-none-any.whl
| Download URL | python_follow-0.1.2-py3-none-any.whl |
|---|---|
| Size | 4.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
78cb101befc698c360cb9791df85a8944b4bcdf37433ea3351cce7004f15d014
|
|
BLAKE2b-256 checksum How to use checksums |
e0eccff86d64e34877e02101cd05131bac0549bbb64ab233235d00bf23ba004a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.6
|