Python error – ImportError: attempted relative import with no known parent package

Question:

So, my files/folders structure is the following:

project/
├─ utils/
│  ├─ module.py
├─ server/
│  ├─ main.py

Inside project/server/main.py I’m trying to import project/utils/module.py using this syntax: from ..utils.module import my_function.

I’m using VSCode, and it even autocomplete for me as I type the module path. But when I run the file project/server/main.py, I get the error in the title.

I’ve read dozens of answers here on stack overflow about this topic but none of them used an example like this.

Asked By: Ricardo Passos

||

Answers:

You can try without using from ..util.module import my_function rather try direct import my_function.

If it doesn’t work you need to create a new file which can be empty named as __init__.py under both utils folder and server folder. __init__.py creates an actual module that can be called for any module.

Answered By: Fatin Ishrak Rafi

Here is a reference that explains this problem well. Basically, the problem is that __package__ is not set when running standalone scripts.

File structure

.
└── project
    ├── server
    │   └── main.py
    └── utils
        └── module.py

project/server/main.py

if __name__ == '__main__':
    print(__package__)

Output

$ python3 project/server/main.py
None

As we can see, the value of __package__ is None. This is a problem because it is the basis of relative imports as stated here:

__package__

… This attribute is used instead of __name__ to calculate explicit relative imports for main modules, as defined in PEP 366…

Where PEP 366 explains this further:

The major proposed change is the introduction of a new module level attribute, __package__. When it is present, relative imports will be based on this attribute rather than the module __name__ attribute.

To resolve this, you can run it as a module via -m flag instead of a standalone script.

Output

$ python3 -m project.server.main  # This can be <python3 -m project.server> if the file was named project/server/__main__.py
project.server

project/server/main.py

from ..utils.module import my_function

if __name__ == '__main__':
    print(__package__)
    print("Main")
    my_function()

Output

$ python3 -m project.server.main
project.server
Main
My function

Now, __package__ is set, which means it can now resolve the explicit relative imports as documented above.

Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.