Importing Notebooks
Importing IPython Notebooks as Modules
It is a common problem that people want to import code from IPython Notebooks. This is made difficult by the fact that Notebooks are not plain Python files, and thus cannot be imported by the regular Python machinery.
Fortunately, Python provides some fairly sophisticated hooks into the import machinery, so we can actually make IPython notebooks importable without much difficulty, and only using public APIs.
import io, os, sys, typesfrom IPython.nbformat import current
from IPython.core.interactiveshell import InteractiveShellImport hooks typically take the form of two objects:
a Module Loader, which takes a module name (e.g.
'IPython.display'), and returns a Modulea Module Finder, which figures out whether a module might exist, and tells Python what Loader to use
def find_notebook(fullname, path=None):
"""find a notebook, given its fully qualified name and an optional path
This turns "foo.bar" into "foo/bar.ipynb"
and tries turning "Foo_Bar" into "Foo Bar" if Foo_Bar
does not exist.
"""
name = fullname.rsplit('.', 1)[-1]
if not path:
path = ['']
for d in path:
nb_path = os.path.join(d, name + ".ipynb")
if os.path.isfile(nb_path):
return nb_path
# let import Notebook_Name find "Notebook Name.ipynb"
nb_path = nb_path.replace("_", " ")
if os.path.isfile(nb_path):
return nb_pathNotebook Loader
Here we have our Notebook Loader. It's actually quite simple - once we figure out the filename of the module, all it does is:
load the notebook document into memory
create an empty Module
execute every cell in the Module namespace
Since IPython cells can have extended syntax, the IPython transform is applied to turn each of these cells into their pure-Python counterparts before executing them. If all of your notebook cells are pure-Python, this step is unnecessary.
The Module Finder
The finder is a simple object that tells you whether a name can be imported, and returns the appropriate loader. All this one does is check, when you do:
import mynotebook
it checks whether mynotebook.ipynb exists. If a notebook is found, then it returns a NotebookLoader.
Any extra logic is just for resolving paths within packages.
Register the hook
Now we register the NotebookFinder with sys.meta_path
After this point, my notebooks should be importable.
Let's look at what we have in the CWD:
So I should be able to import nbimp.mynotebook.
Aside: displaying notebooks
Here is some simple code to display the contents of a notebook with syntax highlighting, etc.
So my notebook has a heading cell and some code cells, one of which contains some IPython syntax.
Let's see what happens when we import it
Hooray, it imported! Does it work?
Hooray again!
Even the function that contains IPython syntax works:
Notebooks in packages
We also have a notebook inside the nb package, so let's make sure that works as well.
Note that the __init__.py is necessary for nb to be considered a package, just like usual.
So now we have importable notebooks, from both the local directory and inside packages.
I can even put a notebook inside IPython, to further demonstrate that this is working properly:
and import the notebook from IPython.utils
This approach can even import functions and classes that are defined in a notebook using the %%cython magic.
Reference : https://nbviewer.jupyter.org
Last updated
Was this helpful?