Home > database >  Proper imports in an installable python project
Proper imports in an installable python project

Time:06-23

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.

  • Related