.ipynb
An .ipynb file is a Jupyter notebook: a JSON document containing an
ordered list of cells, each with its source and, for code cells, the
outputs captured the last time it ran.
{
"cells": [
{ "cell_type": "markdown", "source": ["# Retention analysis\n"] },
{
"cell_type": "code",
"execution_count": 7,
"source": ["df.groupby('cohort').retention.mean().plot()\n"],
"outputs": [
{
"output_type": "display_data",
"data": { "image/png": "iVBORw0KGgo…", "text/plain": ["<Axes: >"] }
}
]
}
],
"metadata": { "kernelspec": { "name": "python3" } },
"nbformat": 4,
"nbformat_minor": 5
}
Outputs live in the file, and that is the whole problem
Storing outputs is what makes a notebook self-describing — you can read someone's analysis without running it. It is also why:
- Diffs are unreadable. A re-run changes execution counts and
re-encodes every image, so a one-character edit shows as thousands of
changed lines.
nbstripoutorjupytextin a pre-commit hook is the standard defence. - Files get big fast. Base64 images inflate by a third. Multi-megabyte notebooks are ordinary, and GitHub's inline renderer gives up on them.
- Merge conflicts corrupt them. A conflicted JSON document is not a notebook, and the error a reader sees is a parse failure, not a merge marker.
What survives an HTML export
jupyter nbconvert --to html notebook.ipynb produces a page with no
kernel behind it.
| Survives | Does not survive |
|---|---|
| Markdown, code, text and table output | ipywidgets sliders and inputs |
| matplotlib and seaborn images | @interact callbacks |
| Plotly, Bokeh, Altair (they embed their own JS) | Anything recomputing on view |
| Stack traces and stderr | input() prompts |
The widget case is the frequent surprise: the export contains the widget state but not the Python that responds to it, so the control renders and does nothing — or renders as a blank area (why widgets don't render).
Interactive charts are the opposite story. Plotly and Bokeh ship their interactivity as JavaScript inside the output, so zoom, hover and legend toggles work in a published HTML export exactly as they did in the notebook — provided the report is served somewhere that lets scripts run (interactive HTML reports).
Sending the analysis, not the file
Sending the .ipynb requires the recipient to have Python, the
environment, and a reason to trust the file. Exporting to HTML and
publishing it gives them a URL that opens on a phone, keeps the charts
live, and can be commented on — so a stakeholder selects the number they
are querying and asks about it there, rather than screenshotting it into
a thread (comment on HTML).
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.