Skip to content

Instantly share code, notes, and snippets.

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__':

This comment has been minimized.

Copy link

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 (:


This comment has been minimized.

Copy link

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.


This comment has been minimized.

Copy link

commented Jan 2, 2019

Thanks. Very useful for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.