I have a very simple MRE that I just can't seem to make work.
.
└── project
├── core
│ ├── __init__.py
│ └── mod_a.py
├── tests
│ └── test_a.py
├── __init__.py
└── test_1.py
# test_1.py
from core.mod_a import class_a
class_a.bar()
# tests/test_a.py
from core.mod_a import class_a
class_a.bar()
# core/mod_a.py
class class_a:
def bar():
print('hello')
This works no problem:
% python3 test1.py
hello
Why does this throw ModuleNotFoundError: No module named 'core':?
% cd tests
% python3 test_a.py
Traceback (most recent call last):
File "/Users//Documents/Development/projects/test/project/tests/test_a.py", line 1, in <module>
from core.mod_a import class_a
ModuleNotFoundError: No module named 'core'
%
Reading through https://docs.python.org/3/tutorial/modules.html#packages, as well as many answers here on SO, this should work for something this basic, but I'll refer to the python docs:
Section 6.4. Packages: The init.py files are required to make Python treat directories containing the file as packages. This prevents directories with a common name, such as string, unintentionally hiding valid modules that occur later on the module search path. In the simplest case, init.py can just be an empty file
Check:
% cd project
% cat __init__.py
% cat core/__init__.py
%
Section 6.4.2 Intra-package References: When packages are structured into subpackages (as with the sound package in the example), you can use absolute imports to refer to submodules of siblings packages. For example, if the module sound.filters.vocoder needs to use the echo module in the sound.effects package, it can use from sound.effects import echo.
Check. In my MRE, test_a.py is using an absolute reference to class_a in core.mod_a:
% cat tests/test_a.py
from core.mod_a import class_a
class_a.bar()
%
I think using a relative import is optional if you don't want to use an absolute import, but trying relative import fails as well:
% tests/test_a.py
from ..core.mod_a import class_a
class_a.bar()
% python3 test_a.py
Traceback (most recent call last):
File "/Users//Documents/Development/projects/test/project/tests/test_a.py", line 1, in <module>
from ..core.mod_a import class_a
ImportError: attempted relative import with no known parent package
%
There's an __init__.py in project and in project/core, and test_1.py can find the package without an issue.
What am I missing here?