Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
run and validate a notebook
#!/usr/bin/env python
"""
simple example script for running notebooks and reporting exceptions.
Usage: `checkipnb.py foo.ipynb [bar.ipynb [...]]`
Each cell is submitted to the kernel, and checked for errors.
"""
import os,sys,time
from Queue import Empty
try:
from IPython.kernel import KernelManager
except ImportError:
from IPython.zmq.blockingkernelmanager import BlockingKernelManager as KernelManager
from IPython.nbformat.current import reads, NotebookNode
def run_notebook(nb):
km = KernelManager()
km.start_kernel(stderr=open(os.devnull, 'w'))
try:
kc = km.client()
except AttributeError:
# 0.13
kc = km
kc.start_channels()
shell = kc.shell_channel
# simple ping:
shell.execute("pass")
shell.get_msg()
cells = 0
failures = 0
for ws in nb.worksheets:
for cell in ws.cells:
if cell.cell_type != 'code':
continue
shell.execute(cell.input)
# wait for finish, maximum 20s
reply = shell.get_msg(timeout=20)['content']
if reply['status'] == 'error':
failures += 1
print "\nFAILURE:"
print cell.input
print '-----'
print "raised:"
print '\n'.join(reply['traceback'])
cells += 1
sys.stdout.write('.')
print
print "ran notebook %s" % nb.metadata.name
print " ran %3i cells" % cells
if failures:
print " %3i cells raised exceptions" % failures
kc.stop_channels()
km.shutdown_kernel()
del km
if __name__ == '__main__':
for ipynb in sys.argv[1:]:
print "running %s" % ipynb
with open(ipynb) as f:
nb = reads(f.read(), 'json')
run_notebook(nb)
@hugadams

This comment has been minimized.

Show comment Hide comment
@hugadams

hugadams Jun 5, 2014

If I have a notebook that has cells ready to be run (say they produce plots form an experiment), and I run this on that notebook, when I open the notebook, the output is still note created. Is it possible to run the notebook offline, and then overwrite the nb with the newly run version?

hugadams commented Jun 5, 2014

If I have a notebook that has cells ready to be run (say they produce plots form an experiment), and I run this on that notebook, when I open the notebook, the output is still note created. Is it possible to run the notebook offline, and then overwrite the nb with the newly run version?

@danielballan

This comment has been minimized.

Show comment Hide comment
@danielballan

danielballan Aug 22, 2014

@hugadams I had the same question, and I discovered this: https://pypi.python.org/pypi/runipy

@hugadams I had the same question, and I discovered this: https://pypi.python.org/pypi/runipy

@GaelVaroquaux

This comment has been minimized.

Show comment Hide comment
@GaelVaroquaux

GaelVaroquaux Jan 8, 2015

Neither the above code, nor runipy, seem to run actually run an IPython notebook as the notebook itself runs it: if I have a "%load" directive in a notebook, and I run all the cells via the interactive menu, the "%load" magic loads the code in a new cell, and this cell is then executed. On the opposite, the various headless runners that I have found just skip the new cell.

It would be really useful to be able to run notebook headless. Currently it is hard to do quality assurance on notebooks.

Neither the above code, nor runipy, seem to run actually run an IPython notebook as the notebook itself runs it: if I have a "%load" directive in a notebook, and I run all the cells via the interactive menu, the "%load" magic loads the code in a new cell, and this cell is then executed. On the opposite, the various headless runners that I have found just skip the new cell.

It would be really useful to be able to run notebook headless. Currently it is hard to do quality assurance on notebooks.

@zonca

This comment has been minimized.

Show comment Hide comment
@zonca

zonca May 11, 2015

@minrk would it be possible to update this script for IPython 3?

zonca commented May 11, 2015

@minrk would it be possible to update this script for IPython 3?

@twiecki

This comment has been minimized.

Show comment Hide comment
@twiecki

twiecki Aug 4, 2015

@minrk Second that request. Tried to run but got a:

    shell.execute("pass")
AttributeError: 'ZMQSocketChannel' object has no attribute 'execute'

twiecki commented Aug 4, 2015

@minrk Second that request. Tried to run but got a:

    shell.execute("pass")
AttributeError: 'ZMQSocketChannel' object has no attribute 'execute'
@kayhan-batmanghelich

This comment has been minimized.

Show comment Hide comment
@kayhan-batmanghelich

kayhan-batmanghelich Jan 4, 2016

@minrk I got the same error as @twiecki. AttributeError: 'ZMQSocketChannel' object has no attribute 'execute' am I missing something?

@minrk I got the same error as @twiecki. AttributeError: 'ZMQSocketChannel' object has no attribute 'execute' am I missing something?

@veroblanchard

This comment has been minimized.

Show comment Hide comment
@veroblanchard

veroblanchard Mar 23, 2016

@twiecki @kayhan-batmanghelich did you fix the issue?

@twiecki @kayhan-batmanghelich did you fix the issue?

@brunsgaard

This comment has been minimized.

Show comment Hide comment
@brunsgaard

brunsgaard Mar 16, 2017

Our solution

import os
import glob
import time
import sys
import traceback

import nbconvert
import nbformat

ep = nbconvert.preprocessors.ExecutePreprocessor(
    extra_arguments=["--log-level=40"],
    timeout=300,
)

def run_notebook(path):
    path = os.path.abspath(path)
    assert path.endswith('.ipynb')
    nb = nbformat.read(path, as_version=4)
    try:
        ep.preprocess(nb, {'metadata': {'path': os.path.dirname(path)}})
    except Exception as e:
        print("\nException raised while running '{}'\n".format(path))
        traceback.print_exc(file=sys.stdout)
        sys.exit(1)


if __name__ == '__main__':
    print('Running notebooks might take a long time...')
    print('===========================================\n')
    for path in glob.iglob('notebooks/**/*.ipynb', recursive=True):
        root, ext = os.path.splitext(os.path.basename(path))
        if root.endswith('_'):
            continue
        s = time.time()
        sys.stdout.write('Now running ' + path)
        sys.stdout.flush()
        run_notebook(path)
        sys.stdout.write(' -- Finish in {}s\n'.format(int(time.time()-s)))


print('\n\033[92m'
      '==========================='
      ' Notebook testing done '
      '==========================='
      '\033[0m')

brunsgaard commented Mar 16, 2017

Our solution

import os
import glob
import time
import sys
import traceback

import nbconvert
import nbformat

ep = nbconvert.preprocessors.ExecutePreprocessor(
    extra_arguments=["--log-level=40"],
    timeout=300,
)

def run_notebook(path):
    path = os.path.abspath(path)
    assert path.endswith('.ipynb')
    nb = nbformat.read(path, as_version=4)
    try:
        ep.preprocess(nb, {'metadata': {'path': os.path.dirname(path)}})
    except Exception as e:
        print("\nException raised while running '{}'\n".format(path))
        traceback.print_exc(file=sys.stdout)
        sys.exit(1)


if __name__ == '__main__':
    print('Running notebooks might take a long time...')
    print('===========================================\n')
    for path in glob.iglob('notebooks/**/*.ipynb', recursive=True):
        root, ext = os.path.splitext(os.path.basename(path))
        if root.endswith('_'):
            continue
        s = time.time()
        sys.stdout.write('Now running ' + path)
        sys.stdout.flush()
        run_notebook(path)
        sys.stdout.write(' -- Finish in {}s\n'.format(int(time.time()-s)))


print('\n\033[92m'
      '==========================='
      ' Notebook testing done '
      '==========================='
      '\033[0m')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment