Skip to content
/ ipynb Public

Package / Module importer for importing code from Jupyter Notebook files (.ipynb)

License

Notifications You must be signed in to change notification settings

ipython/ipynb

Repository files navigation

importnb imports notebooks as modules & packages.

BinderBuild StatusPyPI versionPyPI - Python VersionPyPI - FormatPyPI - Format Conda GitHub tag

pip install importnb

conda install -c conda-forge importnb

importnb works in Python and IPython

Use the Notebook context manager.

For brevity

importnb.loader will find notebooks available anywhere along the sys.path.

    with __import__('importnb').Notebook(): 
        import readme

or explicity

    from importnb import Notebook
    with Notebook(): 
        import readme
    foo = 42
    import readme
    assert readme.foo is 42
    assert readme.__file__.endswith('.ipynb')

Modules may be reloaded

The context manager is required to reload a module.

    from importlib import reload
    with Notebook():
        reload(readme)

Partial loading

The importnb.loader.Partial will import a notebook even if there is an exception. The exception is found on module.__exception.

    with Notebook(exceptions=BaseException):
        try: from . import readme
        except: import readme

Lazy imports

The importnb.loader.Lazy will delay the evaluation of a module until one of its attributes are accessed the first time.

    with Notebook(lazy=True):
        import readme

Capture Outputs

importnb can capture the stdout, stderr, and display in the context manager.

    with Notebook(stdout=True, stderr=True, display=True) as output:
        import readme

Docstring

The first cell is the module docstring.

    if __name__ == '__main__':
        print(readme.__doc__.splitlines()[0])
__importnb__ imports notebooks as modules & packages.

Import notebooks from files

Notebook names may not be valid Python paths. In this case, use Notebook.from_filename.

   Notebook.from_filename('readme.ipynb')

Import under the __main__ context.

   Notebook.from_filename('readme.ipynb', main=True)

Parameterize Notebooks

Literal ast statements are converted to notebooks parameters.

In readme, foo is a parameter because it may be evaluated with ast.literal_val

    from importnb.execute import Parameterize
    f = Parameterize().from_filename(readme.__file__)
    

The parameterized module is a callable that evaluates with different literal statements.

    assert callable(f)
    f.__signature__
<Signature (*, foo=42)>



assert f().foo == 42
assert f(foo='importnb').foo == 'importnb'

Integrations

IPython

Avoid the use of the context manager using loading importnb as IPython extension.

%load_ext importnb

%unload_ext importnb will unload the extension.

Default Extension

importnb may allow notebooks to import by default with

importnb-install

This extension will install a script into the default IPython profile startup that is called each time an IPython session is created.

Uninstall the extension with importnb-install.

Run a notebook as a module

When the default extension is loaded any notebook can be run from the command line. After the importnb extension is created notebooks can be execute from the command line.

ipython -m readme

See the deploy step in the travis build.

py.test

importnb installs a pytest plugin when it is setup. Any notebook obeying the py.test discovery conventions can be used in to pytest. This is great because notebooks are generally your first test.

Setup

To package notebooks add recursive-include package_name *.ipynb

pip install importnb[watch]

importnb exports a watchdog trick to watch files and apply command like operations on their module path.

Tricks File

For example, create a file called tricks.yaml containing

tricks:
- importnb.utils.watch.ModuleTrick:
      patterns: ['*.ipynb']
      shell_command: ipython -m ${watch_dest_path}

Run the watcher in a terminal

watchmedo tricks tricks.yaml

tricks.yaml is a concrete implementation of tricks.yaml

Developer

Format and test the Source Code

    from IPython import get_ipython
    if __name__ == '__main__':
        from pathlib import Path
        from importnb.utils.export import export
        root = 'src/importnb/notebooks/'
        for path in Path(root).rglob("""*.ipynb"""):                
            if 'checkpoint' not in str(path):
                export(path, Path('src/importnb') / path.with_suffix('.py').relative_to(root))
                
            
        __import__('unittest').main(module='src.importnb.tests.test_unittests', argv="discover --verbose".split(), exit=False) 
test_import (src.importnb.tests.test_unittests.TestContext) ... ok
test_reload_with_context (src.importnb.tests.test_unittests.TestContext) ... ok
test_failure (src.importnb.tests.test_unittests.TestExtension) ... unexpected success
test_import (src.importnb.tests.test_unittests.TestExtension) ... ok
test_exception (src.importnb.tests.test_unittests.TestPartial) ... ok
test_traceback (src.importnb.tests.test_unittests.TestPartial) ... ok
test_imports (src.importnb.tests.test_unittests.TestRemote) ... skipped 'requires IP'

----------------------------------------------------------------------
Ran 7 tests in 1.011s

FAILED (skipped=1, unexpected successes=1)
    if __name__ == '__main__':
        !jupyter nbconvert --to markdown readme.ipynb
[NbConvertApp] Converting notebook readme.ipynb to markdown
[NbConvertApp] Support files will be in readme_files/
[NbConvertApp] Making directory readme_files
[NbConvertApp] Making directory readme_files
[NbConvertApp] Writing 8946 bytes to readme.md


if __name__ == '__main__':
    from IPython.display import display, Image
    !pyreverse importnb -opng -pimportnb
    display(*map(Image, ('classes_importnb.png', 'packages_importnb.png')))