Jupyter Notebooks
The classic interactive notebook: code, output, and prose in one document. Notebooks dominate exploratory data science because iteration is instant — see the result of every cell immediately.
Table of Contents
Installation / Setup
pip install notebook pandas matplotlib # or: uv add notebook
jupyter notebook # launch (opens browser at localhost:8888)
Kernels are the Python environments notebooks run in:
# Make your venv available as a notebook kernel
python -m ipykernel install --user --name myenv --display-name "Python (myenv)"
jupyter kernelspec list # see available kernels
Recommended for new work: JupyterLab (the modern interface). Notebooks themselves (.ipynb) are identical in both.
Core Syntax
Cell types
| Cell |
Purpose |
| Code |
Python (or kernel language), output shown below |
| Markdown |
Prose, headings, LaTeX ($...$), images |
| Raw NBConvert |
Passed through unmodified on export |
Keyboard shortcuts (Command mode = Esc first)
| Keys |
Action |
Esc then A / B |
insert cell above / below |
Esc then M / Y |
markdown / code cell |
Esc then DD |
delete cell |
Esc then C / V |
copy / paste cell |
Shift+Enter |
run cell, advance |
Ctrl+Enter / Cmd+Enter |
run cell, stay |
Esc then Shift+↑/↓ |
select multiple cells |
Esc then F |
find in code |
Esc then H |
show help (shortcut list) |
Common Operations
Magics (% line magics, %% cell magics)
%matplotlib inline # render plots inside the notebook
%time slow_function() # time one statement
%%time # time a whole cell
%timeit x.mean() # repeated timing
%load_ext autoreload # auto-reload edited modules
%autoreload 2
%lsmagic # list all magics
%who # variables defined
%whos # ... with types/sizes
%config InlineBackend.figure_format = "retina" # sharp plots on mac
!pip list # shell command (prepend !)
| Useful magic |
Does |
%pdb |
auto-enter debugger on exception |
%debug |
post-mortem debug last error |
%%bash / %%html / %%writefile |
run other languages / write files |
%%capture |
swallow a cell's output |
%run script.py |
run another file in this kernel |
%load_ext watermark + %watermark |
versions for reproducibility |
from ipywidgets import interact, widgets
@interact(lr=widgets.FloatLogSlider(min=-4, max=-1, value=-2),
epochs=(1, 100, 5))
def run(lr, epochs): ...
@interact
def plot(col=df.columns): ...
Practical Examples
1. Standard exploration skeleton
# cell 1 — setup
import pandas as pd, numpy as np, matplotlib.pyplot as plt
%matplotlib inline
%config InlineBackend.figure_format = "retina"
df = pd.read_csv("data.csv")
# cell 2 — glance
df.head(); df.info(); df.isna().sum()
# cell 3+ — each question gets its own cell:
# df.groupby(...).agg(...) / df.plot(...) / hypothesis tests
2. Reproducible report via markdown + code
## Dataset
| Column | Type | Missing |
|--------|------|---------|
...
See figure below — [download the notebook](...).
Common Patterns
# Notebook as a thin shell over package code (best practice)
# mypkg/features.py <- tested, importable
from mypkg.features import build_features
# Notebook as a lab notebook: title, question, hypothesis cells first
# Print nice dataframes in markdown
from IPython.display import display, Markdown
display(df.head(10))
Best Practices
- Run top-to-bottom once before sharing — cells in the wrong order break notebooks for others.
- Keep notebooks thin; move logic to importable
.py modules that pytest can test.
- Use
%autoreload 2 while developing modules so edits appear without restart.
- One question per cell — that's the exploratory workflow.
- Name the notebook well:
01-load-data.ipynb, 02-eda.ipynb (numbered = run order).
- Strip outputs before committing (
nbstripout) for clean git diffs.
- Restart kernel & run all (
Kernel → Restart & Run All) before sharing results.
- Record versions:
%watermark --iversions.
Common Mistakes
| Mistake |
Consequence |
Fix |
| Out-of-order execution |
Wrong results that "worked before" |
Restart & Run All before trusting |
| Plots don't show |
%matplotlib inline missing (or wrong backend) |
Add the magic in the first cell |
| Notebook in git with big outputs |
Huge diffs / merge conflicts |
nbstripout; clear outputs |
| Importing local module edits not seen |
Stale results |
%autoreload 2 |
| Cell state leaking (old variables) |
Silent bugs |
Reset selective vars or restart |
| Long-running cell with no feedback |
Looks frozen |
Add tqdm progress bars / prints |
Troubleshooting
| Symptom |
Cause |
Fix |
Kernel died |
OOM / crash |
Reduce data, restart kernel, add memory |
ModuleNotFoundError in notebook |
Wrong kernel env |
Select the kernel matching the venv with the package |
| Kernel keeps restarting |
Package conflict/crash in imports |
Check logs; recreate kernel |
Connection refused: 8888 |
Server not running |
Relaunch jupyter notebook |
| Notebook won't open |
Corrupt .ipynb JSON |
Recover from autosave / git history |
Official Documentation
Last Updated
2026-09-06 — Initial version.