Search code examples
pythonimportmodulejupyter

`ModuleNotFoundError` in Jupyter Notebook


My notebook and modules are placed like below.

my_directory
  modules  # This is just a directory, not a module
    my_module_1.py
    my_module_2.py
  my_notebook.ipynb

my_module_1.py is imported in my_module_2.py, and my_module_2.py is imported in my_notebook.ipynb like below.

# in `my_module_2.py`
import my_module_1 as something
# in `my_notebook.ipynb`
import modules.my_module_2 as something
from modules.my_module_2 import my_function

If I run my_module_2.py only, then it works correctly. However, if I run the code in my_notebook.ipynb, then ModuleNotFoundError is raised like below.

ModuleNotFoundError                       Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 import modules.my_module_2 as something

File ~\my_directory\modules\my_module_2.py:1, in <module>
----> 1 import my_module_1 as something

ModuleNotFoundError: No module named 'my_module_1'

The notebook works if I change my_module_2.py like below, but then my_module_2.py doesn't work if I run it only...

# in `my_module_2.py`
import modules.my_module_1.py import something

Is there anything I can do to make both the module and the notebook work without changing the structure of the files?


Solution

  • you want your project top folder my_directory path to be searchable by python. you need the absolute path to that folder to be either

    1. on your PYTHONPATH environment variable
    2. your current working directory when invoking python modules/my_module_1.py
    3. your "project directory" for your IDE (like pycharm and spyder and vscode). they secretly add it to your PYTHONPATH or make it your working directory and call python modules/my_module_1.py when you hit run.
    4. create a minimal setup.py and install the package in editable mode pip install -e . to be added to python's search paths.

    any of those methods will allow you to write

    import modules.my_module_1 as something
    import modules.my_module_2 as something_else
    

    in your notebook and in my_module_1.py and in any other project, and they will all resolve correctly.