Problem definition

Suppose we have a Jupyter notebook called “notebook.ipynd”. On the other hand, we developed a module into “mod.py”. In the mod.py, we implement a method called foo as follows:

def foo():
  return "Bar"

Then we import it into the notebook, call it and print the return value of the foo.

from mod import foo

print(foo())

We expect it to print Bar.

But if I change the foo to the following code and rerun the notebook, there will be no change in what is printed.

def foo():
  return "Bar 2"

Solutions

Solution 1

Restart the kernel from the Jupyter menu. It will reload the module so that the changes will be applied. You should restart the kernel and run your notebook from the first cell for any changes.

Solution 2

Reload the module explicitly before importing it. In the following code, we define a method for reloading a module by a given name:

def ralod_moduels(m_name):
    import importlib
    imported_module = importlib.import_module(m_name)
    importlib.reload(imported_module)

We should call the function before importing a module as follow:

ralod_moduels('mod')
from mod import foo

print(foo())

There is no need to run the notebook from the first cell.

Solution 3

An IPython extension called autoreload reloads the modules before executing user code. So at the start of the notebook, we should enable the module, and there is no need to enable it again before importing the modules. So in this point of view, it is better than solution 2. Just add the following code in the first cell of your notebook:

%load_ext autoreload
%autoreload 2

Before importing the module whose changes you want to have tracked, it’ll be re-imported before every cell you execute.

Note: In the Orchest platform, if you want to execute a notebook, you should restart the kernel before executing the first cell (auto-reload extension).

Solution 3 is better than solution two, and two is better than one.