Reputation: 1428
This question was asked a lots of times but none of the solutions seem to help in my case.
I have a directory structure like this
my_project/
main.py
bootstrap/
__init__.py
boot.py
consumer/
__init__.py
main.py
Being at the toplevel directory (myproject
) and executing python3 consumer/main.py
throws an error:
Traceback (most recent call last):
File "consumer/main.py", line 7, in <module>
from bootstrap.boot import MyClass
ImportError: No module named 'bootstrap'
Weird thing is that importing that module using the interpreter works as expected. Running the code from PyCharm also works fine.
I've tried importing with "full path" e.g. from my_project.bootstrap.boot import MyClass
which fails with the same ImportError
. I have also tried using relative imports e.g. from .bootstrap.boot import MyClass
which also failed with SystemError: Parent module '' not loaded, cannot perform relative import
One hack that fixes this is when I add export PYTHONPATH="/root/my_project"
at the bottom of virtualenv activate
script
Upvotes: 0
Views: 203
Reputation: 174614
You are getting this error because module search path only includes the current directory, and not its parents; and since your other module is not in the PYTHONPATH
it isn't available to import.
You can find this out yourself by printing sys.path
in your script.
I created a directory t
with the following:
$ tree
.
├── a.py
├── bar
│ ├── __init__.py
│ └── world.py
└── foo
├── hello.py
└── __init__.py
2 directories, 5 files
Here is the source of hello.py
:
$ cat foo/hello.py
import sys
print("I am in {}".format(__file__))
for path in sys.path:
print(path)
from bar.world import var
print(var)
Now watch what happens, when I execute foo/hello.py
and try to import something from bar/world.py
;
$ python foo/hello.py
I am in foo/hello.py
/home/burhan/t/foo
/usr/lib/python2.7
/usr/lib/python2.7/plat-x86_64-linux-gnu
/usr/lib/python2.7/lib-tk
/usr/lib/python2.7/lib-old
/usr/lib/python2.7/lib-dynload
/home/burhan/.local/lib/python2.7/site-packages
/usr/local/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages
Traceback (most recent call last):
File "foo/hello.py", line 6, in <module>
from bar.world import var
ImportError: No module named bar.world
You can tell from the paths printed that only the system-wide Python library paths, and the current directory of the script is listed. This is why it cannot find bar.world
.
To fix this issue, you can adjust the PYTHONPATH or use relative imports; for example:
$ PYTHONPATH=../t python foo/hello.py
I am in foo/hello.py
/home/burhan/t/foo
/home/burhan/t
/usr/lib/python2.7
/usr/lib/python2.7/plat-x86_64-linux-gnu
/usr/lib/python2.7/lib-tk
/usr/lib/python2.7/lib-old
/usr/lib/python2.7/lib-dynload
/home/burhan/.local/lib/python2.7/site-packages
/usr/local/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages
42
You notice here I am manually overriding the PYTHONTPATH
and adding the common parent of the scripts (42
is coming from bar/world).
To fix this using relative imports, you first have a to create a package in the top most directory, otherwise you'll get the famous Attempted relative import in non-package
error; for more on this and details on how Python 3 importing works, have a look at: Relative imports in Python 3
Upvotes: 4