I have a directory structure similar to the following
meta_project
project1
__init__.py
lib
module.py
__init__.py
notebook_folder
notebook.jpynb
When working in notebook.jpynb
if I try to use a relative import to access a function function()
in module.py
with:
from ..project1.lib.module import function
I get the following error
SystemError Traceback (most recent call last)
<ipython-input-7-6393744d93ab> in <module>()
----> 1 from ..project1.lib.module import function
SystemError: Parent module '' not loaded, cannot perform relative import
Is there any way to get this to work using relative imports?
Note, the notebook server is instantiated at the level of the meta_project
directory, so it should have access to the information in those files.
Note, also, that at least as originally intended project1
wasn't thought of as a module and therefore does not have an __init__.py
file, it was just meant as a file-system directory. If the solution to the problem requires treating it as a module and including an __init__.py
file (even a blank one) that is fine, but doing so is not enough to solve the problem.
I share this directory between machines and relative imports allow me to use the same code everywhere, & I often use notebooks for quick prototyping, so suggestions that involve hacking together absolute paths are unlikely to be helpful.
Edit: This is unlike Relative imports in Python 3, which talks about relative imports in Python 3 in general and – in particular – running a script from within a package directory. This has to do with working within a jupyter notebook trying to call a function in a local module in another directory which has both different general and particular aspects.
Came here searching for best practices in abstracting code to submodules when working in Notebooks. I'm not sure that there is a best practice. I have been proposing this.
A project hierarchy as such:
And from
20170609-Initial_Database_Connection.ipynb
:This works because by default the Jupyter Notebook can parse the
cd
command. Note that this does not make use of Python Notebook magic. It simply works without prepending%bash
.Considering that 99 times out of a 100 I am working in Docker using one of the Project Jupyter Docker images, the following modification is idempotent
So far, the accepted answer has worked best for me. However, my concern has always been that there is a likely scenario where I might refactor the
notebooks
directory into subdirectories, requiring to change themodule_path
in every notebook. I decided to add a python file within each notebook directory to import the required modules.Thus, having the following project structure:
I added the file
project_path.py
in each notebook subdirectory (notebooks/explore
andnotebooks/explain
). This file contains the code for relative imports (from @metakermit):This way, I just need to do relative imports within the
project_path.py
file, and not in the notebooks. The notebooks files would then just need to importproject_path
before importinglib
. For example in0.0-notebook.ipynb
:The caveat here is that reversing the imports would not work. THIS DOES NOT WORK:
Thus care must be taken during imports.
I had almost the same example as you in this notebook where I wanted to illustrate the usage of an adjacent module's function in a DRY manner.
My solution was to tell Python of that additional module import path by adding a snippet like this one to the notebook:
This allows you to import the desired function from the module hierarchy:
Note that it is necessary to add empty
__init__.py
files to project1/ and lib/ folders if you don't have them already.