Jupytext
Jupytext is a Jupyter plugin that allows users to save Jupyter notebooks as various plain text formats, including Markdown documents, Julia, Python, or R scripts. This enables easier version control with tools like Git and allows editing notebooks in standard IDEs. It supports two-way synchronization between the `.ipynb` file and its paired text representation. The current version is 1.19.1, and the library maintains an active release cadence.
Warnings
- breaking Jupytext dropped support for Python 3.8 starting with version 1.17.2, as Python 3.8 reached its End-of-Life. Users on older Python versions must upgrade to at least Python 3.9 or use an older Jupytext version.
- gotcha When using `jupytext --sync` as a `pre-commit` hook, it can sometimes introduce unstaged changes or lead to an infinite loop if not configured correctly. The `--pre-commit-mode` flag is crucial to prevent this behavior.
- gotcha Older versions of Jupytext (pre-1.19.0) could produce warnings about missing or unexpected 'id' fields in cells when converting to certain formats like Pandoc. This was a common validation warning.
- breaking The behavior of `jupytext --set-formats` changed in version 1.17.2. It no longer overrides existing paired files by default, instead respecting existing pairings. Workflows that relied on `--set-formats` to forcibly overwrite paired files may need adjustment.
- gotcha After installing Jupytext, especially the JupyterLab extension, a full restart/reload of the Jupyter server and/or JupyterLab interface is often required for the extension to be recognized and activated correctly.
- gotcha When exporting notebooks to Python scripts (in formats other than `py:percent`) or R Markdown, Jupyter magic commands (`%matplotlib inline`, `%%timeit`) are commented out by default. This is because IDEs do not understand these magics. This behavior can be controlled.
Install
-
pip install jupytext
Imports
- read
from jupytext import read
- write
from jupytext import write
Quickstart
# Create a sample Jupyter notebook file
with open('my_notebook.ipynb', 'w') as f:
f.write('{\"cells\": [{\"cell_type\": \"code\", \"execution_count\": null, \"metadata\": {}, \"outputs\": [], \"source\": [\"print(\\\"Hello from Jupytext!\\\")\"]}, {\"cell_type\": \"markdown\", \"metadata\": {}, \"source\": [\"# A Markdown Cell\"]}], \"metadata\": {\"kernelspec\": {\"display_name\": \"Python 3\", \"language\": \"python\", \"name\": \"python3\"}}, \"nbformat\": 4, \"nbformat_minor\": 4}')
# Pair the .ipynb notebook with a Python script in percent format
# and then synchronize them
import subprocess
print("Pairing notebook.ipynb with notebook.py:percent...")
subprocess.run(['jupytext', '--set-formats', 'ipynb,py:percent', 'my_notebook.ipynb'], check=True)
print("Synchronizing files...")
subprocess.run(['jupytext', '--sync', 'my_notebook.ipynb'], check=True)
print("Generated files:")
subprocess.run(['ls', 'my_notebook.*'])
# Optionally, read the created .py file content
with open('my_notebook.py', 'r') as f:
print('\n--- my_notebook.py content ---')
print(f.read())
# Clean up (optional)
# import os
# os.remove('my_notebook.ipynb')
# os.remove('my_notebook.py')