jupyter-python-tutor
Python Tutor–style step-by-step code visualization directly inside JupyterLab 4.x and Notebook 7 cells.
Quick Start
pip install jupyter-python-tutor
In a Jupyter cell:
%load_ext jupyter_python_tutor
Then use the %%pytutor cell magic:
%%pytutor
x = 3
y = x + 4
print(y)
An interactive trace appears below the cell — drag the slider to navigate through execution, see variable values change at each line, with SVG arrows from frame variables to heap objects (like Python Tutor).
Features
- Interactive slider navigation — drag the slider (or use ◀ ▶ buttons / ← → arrow keys) to scrub through execution steps
- SVG pointer arrows — arrows from frame variables to heap objects, like OPT_Mentor / Python Tutor
- Single-step view — only the current step is shown (not all steps stacked)
- Call stack visualization — global frame + local frames with line numbers
- Heap objects — lists, dicts, class instances, functions, and other objects shown as boxes with arrows pointing to them
- Resizable columns — drag the vertical dividers between code / variables / objects to resize; double-click a divider to collapse/expand
- Auto-height — iframe height follows the tallest column content (no fixed height, no internal scroll)
- AST-based variable filtering — only variables used by the traced code are shown (no IPython internals, no contamination from other cells)
- stdout capture —
print()output is displayed per step - functools.wraps-safe — functions show their true name (
__code__.co_name), not the wrapper's__name__ - Trusted notebook support — renders fully (with JS, CSS, arrows) in trusted notebooks;
jupyter trust notebook.ipynbafter execution - Works with Notebook 7 — compatible with the new Jupyter Notebook 7 (JupyterLab-based)
- Pure Python — no compiled extensions, works in CPython 3.8+
Options
%%pytutor --max-steps 1000 # Limit trace steps (default: 5000)
%%pytutor --raw # Output trace as JSON instead of HTML
%%pytutor --height 400 # Set minimum widget height (default: 500)
%%pytutor --input 2026 # Pre-collected input for input() calls
Examples
Loops
%%pytutor
total = 0
for i in range(5):
total += i
print(f"Sum: {total}")
Functions with recursion
%%pytutor
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
result = factorial(4)
print(result)
Classes and inheritance
%%pytutor
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} says hello"
class Dog(Animal):
def speak(self):
return f"{self.name} barks"
d = Dog("Rex")
print(d.speak())
How It Works
-
Tracing: The
%%pytutormagic compiles the cell code and executes it undersys.settrace(). At each line/call/return event, a snapshot of all local and global variables is captured. AST analysis (ast.parse) extracts the set of names the traced code touches, so only code-relevant variables are shown (filtering out IPython internals and variables from other cells). -
Rendering: The trace steps are rendered as a complete HTML page inside an
<iframe srcdoc="...">. This bypasses JupyterLab 4's HTML sanitizer (which strips<script>,<style>,<button>,<input>, etc. from untrusted output). In trusted notebooks, the iframe renders with full CSS + JavaScript — enabling slider navigation, SVG arrows, draggable dividers, and auto-height. -
Arrows: SVG paths are computed at render time from the bounding boxes of pointer boxes (in frame variables) to heap objects. Arrows redraw on slider navigation, column resize, and window resize.
-
JupyterLab 4 compatibility: JupyterLab 4's HTML sanitizer (DOMPurify) strips JavaScript and external URLs from untrusted notebooks. The iframe
srcdocapproach bypasses this entirely in trusted notebooks. Runjupyter trust your_notebook.ipynbafter executing cells with%%pytutorto ensure the visualization renders correctly.
Limitations
- Trusted notebooks required for full rendering (arrows, slider, dividers). Untrusted notebooks will show a stripped-down version.
sys.settrace()adds overhead — very long loops will be slow; use--max-stepsto limit- Threads are not traced (only the main thread)
License
MIT
Metadata
Release files for jupyter-python-tutor 0.3.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jupyter_python_tutor-0.3.3.tar.gz | 33.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jupyter_python_tutor-0.3.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 59.2 kB
Release files / jupyter_python_tutor-0.3.3.tar.gz
| Download URL | jupyter_python_tutor-0.3.3.tar.gz |
|---|---|
| Size | 33.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5e0aa2ce164661bed2a760f568f9310cbba7fcb83d830eca1e799f8a6a1eeecf
|
|
BLAKE2b-256 checksum How to use checksums |
a065920ba6f27f952d024c1854df0612aa3a22956fa41984d504177b6f25b748
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|
Release files / jupyter_python_tutor-0.3.3-py3-none-any.whl
| Download URL | jupyter_python_tutor-0.3.3-py3-none-any.whl |
|---|---|
| Size | 25.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6f234c7d9e1fc0ab4495794bc672d57f7d271c013d5e459a3f2e78cdd8ed2c85
|
|
BLAKE2b-256 checksum How to use checksums |
5bf4955505de1fb77a28646a1099fcf31adb08f6cd1eed6cc8b9e6f89d09e705
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|