Importnb
%reload_ext tonyfast
__import__('requests_cache').install_cache('importnb'); import inspect, sys, IPython, nbformat, nbconvert, pathlib, json, pytest
Why importnb
?
- Teaches good reproducible habits. Restart and run all
- Promotes less complex notebooks.
- Notebooks can be used as applications.
- Notebooks seed tests.
import importnb
Make notebook
pathlib.Path('demo.ipynb').write_text(json.dumps(
nbformat.v4.new_notebook(cells=[nbformat.v4.new_code_cell("""
foo = 10
print(F"🥇 {foo}")""".splitlines(True))])))
208
import a notebook
with importnb.Notebook():
import demo
F"{demo.__file__}"
'demo.ipynb'
Are the notebooks reload-able?
with pytest.raises(ModuleNotFoundError):
importnb.reload(demo)
🤝 change the notebook
pathlib.Path('demo.ipynb').write_text(json.dumps(
nbformat.v4.new_notebook(cells=[nbformat.v4.new_code_cell("""
foo = "What"
print(F"⓶ {foo}")""".splitlines(True))])))
208
with importnb.Notebook():
importnb.reload(demo)
⓶ What
https://github.com/deathbeds/importnb
Relative imports.
Import notebooks in "__init__.py" and "__main__.py"
files.
IPython.display.display(
IPython.display.Code("https://gist.githubusercontent.com/tonyfast/fee98e31e3da90c3606c5dc14a703f0c/raw/780b50a6708b40c56274e4c66c82eeb48bee50e6/__init__.py".text()))
__all__ = 'jschema',
with __import__('importnb').Notebook(lazy=True):
from .jschema import *
Notebooks that make extensions
IPython.display.display(
IPython.display.Code("https://raw.githubusercontent.com/tonyfast/gists/master/tonyfast/__init__.py".text()))
def load_ipython_extension(shell):
with __import__('importnb').Notebook(): from . import jschema, ainteractive
jschema.load_ipython_extension(shell)
ainteractive.load_ipython_extension(shell)
def unload_ipython_extension(shell):
with __import__('importnb').Notebook(): from . import jschema, ainteractive
jschema.unload_ipython_extension(shell)
ainteractive.unload_ipython_extension(shell)
__name__ == '__main__'
is important
In notebooks, we are working in the application. It hasn’t been named yet.
What does importnb
do?
...
temporarily modifies the sys.path_hooks
used to discover typical python files.
Before
inspect.getclosurevars(sys.path_hooks[1]).nonlocals['loader_details']
((_frozen_importlib_external.ExtensionFileLoader,
['.cpython-37m-darwin.so', '.abi3.so', '.so']),
(_frozen_importlib_external.SourceFileLoader, ['.py']),
(_frozen_importlib_external.SourcelessFileLoader, ['.pyc']))
After
with importnb.Notebook(): print(inspect.getclosurevars(sys.path_hooks[1]).nonlocals['loader_details'])
((functools.partial(<class 'importnb.loader.Notebook'>, lazy=False, fuzzy=True, markdown_docstring=True, position=0, main=False), ('.ipynb',)), (<class '_frozen_importlib_external.ExtensionFileLoader'>, ['.cpython-37m-darwin.so', '.abi3.so', '.so']), (<class '_frozen_importlib_external.SourceFileLoader'>, ['.py']), (<class '_frozen_importlib_external.SourcelessFileLoader'>, ['.pyc']))
Parameterized notebooks
%%capture
f = importnb.Parameterize.load('demo.ipynb')
f(foo=' 🙏')
⓶ 🙏
<module 'demo' from 'demo.ipynb'>
def _(l:(0, 100)): f(foo=l)
_
<function _ at 0x113dd4d90>
interactive(children=(IntSlider(value=50, description='l'), Output()), _dom_classes=('widget-interact',))
😫 CLI looks busted.
Written on September 24, 2019