Skip to content

Instantly share code, notes, and snippets.

Last active November 5, 2021 02:45
What would you like to do?
Run 2to3 on IPython notebooks
#!/usr/bin/env python3
To run: python3 notebook-or-directory
# Authors: Thomas Kluyver, Fernando Perez
# See:
import argparse
import pathlib
from nbformat import read, write
import lib2to3
from lib2to3.refactor import RefactoringTool, get_fixers_from_package
def refactor_notebook_inplace(rt, path):
def refactor_cell(src):
#print('\n***SRC***\n', src)
tree = rt.refactor_string(src+'\n', str(path) + '/cell-%d' % i)
except (lib2to3.pgen2.parse.ParseError,
return src
return str(tree)[:-1]
print("Refactoring:", path)
nb = read(str(path), as_version=4)
# Run 2to3 on code
for i, cell in enumerate(nb.cells, start=1):
if cell.cell_type == 'code':
if cell.execution_count in (' ', '*'):
cell.execution_count = None
if cell.source.startswith('%%'):
# For cell magics, try to refactor the body, in case it's
# valid python
head, source = cell.source.split('\n', 1)
cell.source = head + '\n' + refactor_cell(source)
cell.source = refactor_cell(cell.source)
# Update notebook metadata
nb.metadata.kernelspec = {
'display_name': 'Python 3',
'name': 'python3',
'language': 'python',
if 'language_info' in nb.metadata:
nb.metadata.language_info.codemirror_mode = {
'name': 'ipython',
'version': 3,
nb.metadata.language_info.pygments_lexer = 'ipython3'
nb.metadata.language_info.pop('version', None)
write(nb, str(path))
def main(argv=None):
ap = argparse.ArgumentParser()
ap.add_argument('path', type=pathlib.Path,
help="Notebook or directory containing notebooks")
options = ap.parse_args(argv)
avail_fixes = set(get_fixers_from_package('lib2to3.fixes'))
rt = RefactoringTool(avail_fixes)
if options.path.is_dir():
for nb_path in options.path.rglob('*.ipynb'):
refactor_notebook_inplace(rt, nb_path)
refactor_notebook_inplace(rt, options.path)
if __name__ == '__main__':
Copy link

drevicko commented Aug 9, 2017

Traceback (most recent call last):
  File "", line 80, in <module>
  File "", line 75, in main
    refactor_notebook_inplace(rt, nb_path)
  File "", line 41, in refactor_notebook_inplace
    head, source = cell.source.split('\n', 1)
ValueError: not enough values to unpack (expected 2, got 1)

I think the offending bit of the ipynb file is this:

   "source": [
    "%%timeit p={\"$push\":{'events':event}}"

Catching the exception and ignoring looks to solve it (:

Copy link

EWouters commented Apr 11, 2018

I used this to make an extension for Jupyter Notebooks that can convert cells (or whole notebooks) from python 2 to 3 with the click of a button. It has been added to jupyter_contrib_nbextensions. I mentioned your contribution in the readme.

Find it here.

Copy link

urkh commented Jan 2, 2019

Thanks. Very useful for me.

Copy link

nyck33 commented Mar 6, 2020

Great docs but where is the simplied, "pip install this", "conda install this" and you're good to go instructions?

Copy link

Since @EWouters turned this script into an nbextension, you can refer to the jupyter-contrib-nbextensions docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment