ModuleNotFoundError when running individual Python files with absolute imports

68 Views Asked by At

ModuleNotFoundError running Python 3.8.x

I'm building a python package containing classes and functions each with verbose tests. Inside the package I'm trying to use these building blocks to provide end-to-end uses and examples by using absolute imports at the top of these files (like in my tests).

The project structure is as follows:

.
├── __init__.py
├── setup.py
├── examples
│   ├── __init__.py
│   └── end_to_end_1.py
├── tests
│   ├── __init__.py
│   └── utils
│       ├── __init__.py
│       ├── test_useful_one.py
│       └── test_useful_two.py
└── utils
    ├── __init__.py
    ├── useful_one.py
    └── useful_two.py

I'm running all tests from the package root using python -m unittest tests/**/*.py, and both test files contain absolute package imports from utils like so,

from utils.useful_one import UsefulClass

this approach is succesful in running the tests and importing the UsefulClass class into the test files.

My issue arises when trying to use the same import statement inside the examples/end_to_end_1.py module and executing the file (again from the root of the package) using

python examples/end_to_end_1.py

Now I get a runtime ModuleNotFoundError: No module named 'utils'.

In trying to follow the python language guidelines I'm trying to use absolute imports where possible but to no avail.

I have definitely misunderstood how the __init__.py files are supposed to tell the runtime where to resolve packages from. I don't think this use case is abnormal, since I see this same pattern inside node packages and ruby gems all the time.

Makeshift (Temporary) Solution

At the moment to solve this I have applied the solution from Absolute import results in ModuleNotFoundError which, despite working, seems not too scalable when the repository is publically available and I feel like the Python ecosystem will have a solution for this issue. As Raymond Hettinger says, it feels like..

There must be a better way!

0

There are 0 best solutions below