0

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

3
  • Have you tried "from my_project.bootstrap import MyClass" ? Commented Aug 18, 2016 at 8:25
  • Yes, I've edited the question, thank you. Commented Aug 18, 2016 at 8:34
  • 1
    try adding an __init__.py to the my_project/ directory, see if that helps Commented Aug 18, 2016 at 8:41

1 Answer 1

4

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

Sign up to request clarification or add additional context in comments.

1 Comment

would you mind going through how to create the top level as a package?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.