Thread debugging and deadlock detection tool
Project description
threadle
Observabilidad de concurrencia en Python. threadle modela un grafo wait-for (hilos y cerrojos instrumentados), detecta ciclos compatibles con deadlock y ofrece líneas de tiempo y gráficos para razonar sobre contención antes de optimizar a ciegas. Incluye un camino opcional para asyncio (dependencias entre tareas, Gantt de tareas).
No intercepta threading.Lock anónimos: el estado solo refleja lo que conectas con TrackedLock, decoradores y las APIs de trazado. Pensado para servicios con locks explícitos, pruebas de carga reproducibles y depuración de regresiones de diseño.
Highlights
- Grafo wait-for — Aristas dirigidas thread → lock (espera) y lock → thread (posesión); ciclos sobre un
networkx.DiGraph. - Informes —
DeadlockReportcon resumen legible y JSON estable (to_json) para pipelines y tickets. - Timeline — Estados running / waiting / holding y Gantt por hilo; lectura lógica de contención (el GIL de CPython sigue aplicando al bytecode).
- CLI —
threadle detect,snapshot,demoen el proceso que importó la librería. - Demo — Tutorial en el repo:
notebook/demo.ipynb(no forma parte del wheel en PyPI).
Instalación
Requiere Python ≥ 3.11. Dependencias: networkx, matplotlib, matplotlib-inline (figuras en Jupyter y entornos sin DISPLAY).
pip install threadle
uv add threadle
Ejemplo mínimo
import threadle as tl
# Usa TrackedLock en tus hilos en lugar de threading.Lock donde quieras trazabilidad.
lock_a = tl.TrackedLock("A")
lock_b = tl.TrackedLock("B")
# ... tu código ...
tl.analyze_deadlocks() # DeadlockReport
print(tl.export_debug_bundle_json()) # snapshot completo JSON
Para trazado de línea de tiempo y análisis en bloque:
with tl.Session(trace_timeline=True, reset_tracker=False):
# código instrumentado
report = tl.analyze_deadlocks()
Session expone trace_timeline, reset_tracker (solo tests o demos aislados) y clear_events_on_enter.
Conceptos
| Término | Significado |
|---|---|
| Instrumentación | TrackedLock + trace / trace_thread + Session y registro de eventos. |
| Wait-for | Grafo dirigido; relaciones held_by y waits_for en las aristas cuando el tracker las rellena. |
| Timeline | Serie temporal de estados inferidos a partir de trazas; alimenta visualize_gantt / export_gantt. |
Mapa de la API pública
| Ámbito | API representativa |
|---|---|
| Locks | TrackedLock |
| Análisis | detect_deadlocks, analyze_deadlocks, DeadlockReport |
| Exportación | export_debug_bundle_json, export_tracker_state_dict, export_debug_bundle_dict |
| Trazado (threads) | trace, trace_thread, Session, start_tracing, stop_tracing, get_events, clear_events |
| Figuras (threads) | visualize, visualize_gantt, export_gantt |
| asyncio | Carga diferida: start_async_tracing, traced_await, build_async_dependency_graph, visualize_async_gantt, export_async_gantt, … (threadle.__getattr__) |
Línea de comandos
El binario threadle opera sobre el mismo proceso que importó la librería (no es un depurador externo al proceso).
| Comando | Efecto |
|---|---|
threadle detect |
Salida de detect_deadlocks(). |
threadle detect --json |
JSON de analyze_deadlocks(). |
threadle snapshot |
export_debug_bundle_json() completo. |
threadle demo |
Demo de deadlock incluida en el paquete. |
threadle demo --visualize -o grafo.png |
PNG del grafo de la demo. |
Visualización
visualize: grafo wait-for dirigido (flechas; colores por relación cuando hay metadatos).visualize_gantt: una fila por hilo; paletassemanticoper_thread.- asyncio:
visualize_async_gantty export PNG análogo.
Gantt HTML interactivo (hilos): extra plotly → pip install "threadle[plotly]".
CI, regresiones y post-mortems
export_debug_bundle_json() y DeadlockReport.to_json() se prestan a artefactos en pipelines, adjuntos en incidencias y comparación de snapshots entre versiones.
Extras
| Extra | Contenido |
|---|---|
threadle[plotly] |
Plotly para export HTML del Gantt (donde aplique). |
threadle[dev] |
pytest, nbformat, nbclient, ipykernel, nbconvert. |
Desarrollo
git clone https://github.com/lucianoramirezs/threadle.git && cd threadle
pip install -e ".[dev]"
pytest -q
Con uv: uv sync --all-extras y uv run pytest -q.
Regenerar el notebook de demo: python scripts/generate_notebook_demo.py. Los artefactos bajo notebook/outputs/ suelen ignorarse en git; el .ipynb vive en el repositorio, no en el wheel de PyPI.
Enlaces
| Recurso | URL |
|---|---|
| Código | github.com/lucianoramirezs/threadle |
| Paquetes | pypi.org/project/threadle |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file threadle-0.1.0.tar.gz.
File metadata
- Download URL: threadle-0.1.0.tar.gz
- Upload date:
- Size: 27.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6de1a9fb274ee0407302d10e265912bc9057a2036e71c53c63c70e5d6468302
|
|
| MD5 |
8eb96f0ee4439cea5ac7c86fdd7a15e4
|
|
| BLAKE2b-256 |
20d405642a2e583c7a35867a6186749541783c8e2b2a0f77718a96dfff3cdb15
|
File details
Details for the file threadle-0.1.0-py3-none-any.whl.
File metadata
- Download URL: threadle-0.1.0-py3-none-any.whl
- Upload date:
- Size: 33.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
acb198a9b196d0214eef73efa79110408037074501cba3c21a6180dda275abbf
|
|
| MD5 |
3e550b9bbda12606d8df4d5fef4b03f8
|
|
| BLAKE2b-256 |
ce79dbc47bb8ccb66554a4d02ac3b02f9f905dba42df85ec960c0ebef7040830
|