178

Interactive Python (ipython) is simply amazing, especially as you are piecing things together on the fly... and does it in such a way that it is easy to go back.

However, what seems to be interesting is the use-case of having multiple ipython notebooks (ipynb files). It apparently seems like a notebook is NOT supposed to have a relationship with other notebooks, which makes sense, except that I would love to import other ipynb files.

The only workaround I see is converting my *.ipynb files into *.py files, which then can be imported into my notebook. Having one file hold everything in a project is a bit weird, especially if I want to really push for code-reuse (isn't that a core tenet of python?).

Am I missing something? Is this not a supported use case of ipython notebooks? Is there another solution I can be using for this import of an ipynb file into another notebook? I'd love to continue to use ipynb, but it's really messing up my workflow right now :(

Lerner Zhang
  • 6,184
  • 2
  • 49
  • 66
Andrew Harris
  • 1,975
  • 2
  • 13
  • 8
  • Possible duplicate: http://stackoverflow.com/questions/19082397/including-a-notebook-in-another-notebook-in-ipython – Warren Weckesser Nov 25 '13 at 07:23
  • 3
    You can start the notebook server with `--script` to save .py copies of your notebooks. In IPython 2.0, you'll be able to `%run` a notebook. We're still working out better mechanisms for code reuse. – Thomas K Nov 25 '13 at 19:14
  • https://stackoverflow.com/q/20186344/478206, https://stackoverflow.com/q/19082397/478206 and https://stackoverflow.com/q/19564625/478206 are all asking the same question. – Robie Basak Dec 05 '17 at 13:57
  • 1
    [This example](http://nbviewer.jupyter.org/github/jupyter/notebook/blob/master/docs/source/examples/Notebook/Importing%20Notebooks.ipynb) shows how to import IPython notebooks as modules without exporting duplicates as scripts. – minrk Nov 27 '13 at 20:48

11 Answers11

209

It is really simple in newer Jupyter:

%run MyOtherNotebook.ipynb

See here for details.

Official docs: %run IPython magic command

wjandrea
  • 28,235
  • 9
  • 60
  • 81
johndodo
  • 17,247
  • 15
  • 96
  • 113
  • 5
    %run MyOtherNotebook.ipynb did the job for me. (no ' ') – Florian H Jul 11 '17 at 07:29
  • 9
    Be careful, this method will completely run the child notebook. You can add a check `__name__ == '__main__' and '__file__' not in globals()` to verify if you're in the child notebook. (from https://blog.sicara.com/present-data-science-results-jupyter-notebook-import-into-another-108433bc8505) – Flavian Hautbois Sep 25 '17 at 14:31
  • This doesn't work for me. I get the following: `NameError Traceback (most recent call last) C:\Dev\Study\python\interpret_basics\nursery_utils.IPYNB in () 3 { 4 "cell_type": "code", ----> 5 "execution_count": null, 6 "metadata": { 7 "collapsed": true NameError: name 'null' is not defined` – julianhatwell Nov 08 '17 at 09:53
  • 15
    %run 'MyOtherNotebook.ipynb' ERROR:root:File `u'MyOtherNotebook.ipynb.py'` not found. – user3673 Apr 06 '18 at 00:24
  • 1
    @Kocur4d Thanks for fixing! Interestingly enough it worked for me (with quotes) when I tried it, but examples in documentation don't have any quotes. – johndodo May 28 '18 at 16:24
  • 5
    if anyone comes across that, you can also use full path like %run "/path/to/my/file/notebook.ipynb" – Jeremie Jul 26 '18 at 15:28
  • 1
    @user3673: I had the same problem and it was caused by the ";" at the end of the command. Removing it fixed the issue. – Stephan Jul 04 '19 at 07:49
  • this is soo coool! thank you! A quick qs - are all functions from imported file loaded in memory or imported only when called? – rishi jain Jul 10 '19 at 10:09
  • The disadvantage of this compared to using import_ipynb is that if you turn your notebooks to plain python scripts the later still works. – Zuzu Corneliu Aug 30 '19 at 22:31
  • How to run only one function instead of all cells when we use this command, or if there is one could do that? – Jason Nov 05 '19 at 20:56
  • I do make frequent changes to the imported file - MyOtherNotebook.ipynb . And the problem is that I need to go to the top of the jupyter notebook to run the command each time. Is there any auto compile functionality for included files? – rishi jain Nov 07 '19 at 10:28
  • Why would %run MyOtherNotebook.ipynb work brilliantly in IDEs like Spyder and PyCharm, but not in VSCode? I keep getting this error in VSCode 'SyntaxError: invalid syntax' but it runs fine and beautifully in other IDEs. – Ankhnesmerira Mar 18 '21 at 04:12
  • This is how it worked for me (both files are in the same directory): %run ../MyOtherNotebook.ipynb – NoamG Feb 01 '23 at 09:00
57

Install my helper library from the command prompt:

pip install import-ipynb

Import it from your notebook:

import import_ipynb

Now import your .ipynb notebook as if it was a .py file

import TheOtherNotebook

This python-ipynb module is just one file and it strictly adheres to the official howto on the jupyter site.

PS It also supports things like from A import foo, from A import * etc

PPS Works with subdirectories: import A.B

axil
  • 1,558
  • 16
  • 17
  • 1
    @Crash `pip install import-ipynb` also works and installs just the same package, but since python won't allow you to write `import import-ipynb` and considering it's just one file, `pip install import_ipynb` looks more consistent to me. – axil Jun 23 '18 at 06:45
  • 3
    Is there any difference between `import nbimporter` and `import import_ipynb`? – Fractale Mar 01 '19 at 02:24
  • 5
    This doesn't work at all in my Jupyter with Python 3 – Sebastialonso May 10 '20 at 00:49
  • @Sebastialonso What exactly doesn't work? Describe what you do and what error messages you see. Ideally open a ticket on github. – axil May 11 '20 at 03:15
  • @axil I have a same error where it doesn't work for me in Py3. It gives me following error - ModuleNotFoundError: No module named 'A' PS:A.ipynb exist in same folder – Soman Dubey Jun 21 '20 at 19:09
  • @SomanDubey please open a ticket with a detailed description here: https://github.com/axil/import-ipynb/issues – Antony Hatchkins Jun 22 '20 at 20:21
  • does this require the directory, where the notebook to be imported located, have an init.py ? – Luk Aron Jan 02 '21 at 18:59
  • @axil my ipynb imported successfully. But it has not attributes i.e. all the defined classes, functions, variables etc . The `dir(notebookname)` list the following things only `['__doc__','__file__','__loader__','__name__','__package__','__path__','__spec__']` – Girish Kumar Chandora Mar 21 '21 at 04:03
  • @GirishKumarChandora Works for me. Can you provide the minimal reproducible example (eg as a gist)? – axil Mar 24 '21 at 06:27
  • @LukAron No it doesn't. Works without `__init__.py` – axil Mar 24 '21 at 06:28
  • 1
    @axil. My apologies, I did a mistake at that time during execution, which I came to know later. Now it is working fine. Tysm – Girish Kumar Chandora Mar 24 '21 at 06:32
  • `pip install python-ipynb` doesn't work for me, I used `pip install import-ipynb` instead (as said in the GitHub repo). – Tomergt45 Jul 30 '21 at 12:48
52

Run

!pip install ipynb

and then import the other notebook as

from ipynb.fs.full.<notebook_name> import *

or

from ipynb.fs.full.<notebook_name> import <function_name>

Make sure that all the notebooks are in the same directory.

Edit 1: You can see the official documentation here - https://ipynb.readthedocs.io/en/stable/

Also, if you would like to import only class & function definitions from a notebook (and not the top level statements), you can use ipynb.fs.defs instead of ipynb.fs.full. Full uppercase variable assignment will get evaluated as well.

Malgo
  • 1,871
  • 1
  • 17
  • 30
  • 4
    What if my file name has whitespace in it? – Sameh Mar 09 '20 at 15:10
  • 6
    It is advised to not keep any whitespace in your file name – Malgo Mar 12 '20 at 05:38
  • 6
    Note that in both cases described, the imported notebook is executed in full. The `ipynb` package also supports partial execution of definitions only. It is an official package by IPyhton, so i believe that this should be the accepted answer. – amka66 Apr 27 '20 at 02:41
  • 4
    Can this import notebooks inside a folder? for example ```MyFolder/book.ipynb``` – bones225 May 27 '20 at 18:48
  • 1
    This was looking good but falls over when it encounters e.g. %matplotlib inline.... – jtlz2 Jul 20 '20 at 14:31
  • 1
    @Malgo getting error of language version after execution. – Girish Kumar Chandora Mar 21 '21 at 03:55
  • 1
    @GirishKumarChandora apologies for the late reply but can you please describe the issue in detail? – Malgo Apr 15 '21 at 11:19
  • 1
    @Malgo its been a long time, I also forgot what kind of issues I faced that time. I use different approach to fulfill my desire at that time. Thanks for your help and time. – Girish Kumar Chandora Apr 15 '21 at 11:24
  • I am trying to import ipynb from one notebook from another notebook in Azure Databricks workspce. While importing using from ipynb.fs.full. import * I am getting Key Error : __Package__ – Nandhakumar Rajendran Sep 07 '21 at 06:43
25

Install ipynb from your command prompt

pip install import-ipynb

Import in your notebook file

import import_ipynb

Now use regular import command to import your file

import MyOtherNotebook
outofworld
  • 354
  • 5
  • 11
7

%run YourNotebookfile.ipynb is working fine;

if you want to import a specific module then just add the import command after the ipynb i.e YourNotebookfile.ipynb having def Add()

then you can just use it

%run YourNotebookfile.ipynb import Add
6

The above mentioned comments are very useful but they are a bit difficult to implement. Below steps you can try, I also tried it and it worked:

  1. Download that file from your notebook in PY file format (You can find that option in File tab).
  2. Now copy that downloaded file into the working directory of Jupyter Notebook
  3. You are now ready to use it. Just import .PY File into the ipynb file
Kurt Van den Branden
  • 11,995
  • 10
  • 76
  • 85
Yash Bansal
  • 402
  • 5
  • 10
  • hmm...I converted the callee.ipync to callee.py file, and then uploaded the callee.py file onto the notebook under the same folder with caller.ipync, and the in caller.ipync I just wrote `import callee`, just couldn't work. – Elsa Lin Feb 09 '17 at 06:18
  • p.s. the IPython is version: 5.1.0. – Elsa Lin Feb 09 '17 at 06:28
6

You can use import nbimporter then import notebookName

Fractale
  • 1,503
  • 3
  • 19
  • 34
  • +1, nbimporter works like a charm for me, also it can be installed using conda: `conda install -c conda-forge importnb` – Zuku Mar 06 '20 at 07:53
3

The issue is that a notebooks is not a plain python file. The steps to import the .ipynb file are outlined in the following: Importing notebook

I am pasting the code, so if you need it...you can just do a quick copy and paste. Notice that at the end I have the import primes statement. You'll have to change that of course. The name of my file is primes.ipynb. From this point on you can use the content inside that file as you would do regularly.

Wish there was a simpler method, but this is straight from the docs.
Note: I am using jupyter not ipython.

import io, os, sys, types
from IPython import get_ipython
from nbformat import current
from IPython.core.interactiveshell import InteractiveShell


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_path


class NotebookLoader(object):
    """Module Loader for Jupyter Notebooks"""
    def __init__(self, path=None):
        self.shell = InteractiveShell.instance()
        self.path = path

    def load_module(self, fullname):
        """import a notebook as a module"""
        path = find_notebook(fullname, self.path)

        print ("importing Jupyter notebook from %s" % path)

        # load the notebook object
        with io.open(path, 'r', encoding='utf-8') as f:
            nb = current.read(f, 'json')


        # create the module and add it to sys.modules
        # if name in sys.modules:
        #    return sys.modules[name]
        mod = types.ModuleType(fullname)
        mod.__file__ = path
        mod.__loader__ = self
        mod.__dict__['get_ipython'] = get_ipython
        sys.modules[fullname] = mod

        # extra work to ensure that magics that would affect the user_ns
        # actually affect the notebook module's ns
        save_user_ns = self.shell.user_ns
        self.shell.user_ns = mod.__dict__

        try:
        for cell in nb.worksheets[0].cells:
            if cell.cell_type == 'code' and cell.language == 'python':
                # transform the input to executable Python
                code = self.shell.input_transformer_manager.transform_cell(cell.input)
                # run the code in themodule
                exec(code, mod.__dict__)
        finally:
            self.shell.user_ns = save_user_ns
        return mod


class NotebookFinder(object):
    """Module finder that locates Jupyter Notebooks"""
    def __init__(self):
        self.loaders = {}

    def find_module(self, fullname, path=None):
        nb_path = find_notebook(fullname, path)
        if not nb_path:
            return

        key = path
        if path:
            # lists aren't hashable
            key = os.path.sep.join(path)

        if key not in self.loaders:
            self.loaders[key] = NotebookLoader(path)
        return self.loaders[key]

sys.meta_path.append(NotebookFinder())

import primes
germ13
  • 532
  • 1
  • 5
  • 12
2

There is no problem at all using Jupyter with existing or new Python .py modules. With Jupyter running, simply fire up Spyder (or any editor of your choice) to build / modify your module class definitions in a .py file, and then just import the modules as needed into Jupyter.

One thing that makes this really seamless is using the autoreload magic extension. You can see documentation for autoreload here:

http://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html

Here is the code to automatically reload the module any time it has been modified:

# autoreload sets up auto reloading of modified .py modules
import autoreload
%load_ext autoreload
%autoreload 2

Note that I tried the code mentioned in a prior reply to simulate loading .ipynb files as modules, and got it to work, but it chokes when you make changes to the .ipynb file. It looks like you need to restart the Jupyter development environment in order to reload the .ipynb 'module', which was not acceptable to me since I am making lots of changes to my code.

David Miller
  • 512
  • 2
  • 4
  • 17
1

Please make sure that you also add a __init__.py file in the package where all your other .ipynb files are located.

This is in addition to the nbviewer link that minrk and syi provided above.

I also had some similar problem and then I wrote the solution as well as a link to my public google drive folder which has a working example :)

My Stackoverflow post with step by step experimentation and Solution:

Jupyter Notebook: Import .ipynb file and access it's method in other .ipynb file giving error

Hope this will help others as well. Thanks all!

anugrah
  • 187
  • 1
  • 1
  • 10
0

While the '%run childNotebook.ipynb' command is a pretty simple and useful solution (as mentioned in a previous answer), you should be cautious about using it when the child file is also using another '%run grandChildNotebook.ipynb' in it, but is located in another directory! It can result in duplicate run of files, and is also error prone (as the child no longer uses the same path as its parents, while when running, Jupyter assumes it to do so!)

For resolving the mentioned problem, one solution may be this: just before importing any file, first check where the current directory is located, and then act based on that. Here is an example:

if 'myFolder' in os.getcwd():
    %run graindChildNotebook.ipynb
else:
    %run myFolder/grandChildNotebook.ipynb

In the above example, it is first checked if we are in the 'myFolder' directory or not. If so, we would find out that the 'grandChildNotebook' is in the same directory and it would be enough to run it as normal. Else, we need to run it by adding the name of the folder this file is located in.

Be careful that it is just an example, and you should do your personalized solution based on your case!