I'm trying to clean a python project on pypi to make it installable. It has the following structure (very simplified)
project_x/
project_x/
pack_a/
__init__.py
mod_a1.py
mod_a2.py
pack_b/
__init__.py
mod_b.py
setup.py
README
...
In mod_a1.py
there is something like from pack_a.mod_a2 import something
.
So I added, to the setup.py, the line package_dir: {"": "project_x"}
for this to work.
However, mod_b.py
uses relative imports: from ..pack_a.mod_a import ...
.
This fails with
ImportError: attempted relative import beyond top-level package
What is the correct way to handle this? Avoid using relative imports? Writing full paths, such a from project_x.pack_a import...
everywhere? Or something smart in the setup.py?
CodePudding user response:
The problem seems to be that pack_a
(and its modules) assumes itself to be a top-level package, while pack_b
(and its modules) assumes itself to be a sub-package of project_x
.
You cannot have both. Instead, you will need to reconcile their implementation.
If you use package_dir: {"": "project_x"}
, then both packages should use absolute imports towards each other (but internally they can use either relative/absolute imports). Please note that this option also means that project_x
will not exist as an importable item, i.e. users will NOT be able to execute the following statements:
import project_x
from project_x import pack_a, pack_b
If you remove package_dir
, then any statement in the form of:
from pack_a import ... # => it should be from project_x.pack_a ...
from pack_b import ... # => it should be from project_x.pack_b ...
will be wrong because pack_a
and pack_b
are not top-level packages.
Instead you could use relative imports, or fix the absolute imports to start with project_x
.