20

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.

Ricardo Passos
  • 373
  • 1
  • 3
  • 10
  • 1
    if your project is more than a single file, it's generally saner to run `python -m your.main.module` rather than `python your/main/module.py`, so that `sys.path` is used to find the main module, rather than defined based on the main module. – o11c Aug 27 '21 at 23:17
  • Add `__init__.py` in the subdirectories and set PYTHONPATH= – drum Aug 27 '21 at 23:19

2 Answers2

33

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.

0

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.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Fatin Ishrak Rafi
  • 339
  • 1
  • 3
  • 11