Reputation: 319
Consider the following directory
myProject
myCode.py
__init__.py
myProject2
__init__.py
myProject2Inner
myCode.py
__init__.py
myLibrary
__init__.py
myPackage1
__init__.py
myPackage1Code.py
myPackage2
__init__.py
myPackage2Code.py
If myCode.py
is dependent on myPackage1Code.py
and myPackage1Code.py
is dependent on myPackage2Code.py
I am currently doing the following
sys.path.append(os.path.abspath('../myLibrary/myPackage2/'))
import myPackage2Code
in myPackage1Code.py
to make the code run successfully. But this is obviously really bad since the library import path is entirely dependent on who is using it. For example if myProject2Inner
requires myPackage1
then the code above wouldn't work.
I would have to do
sys.path.append(os.path.abspath('../../myLibrary/myPackage2/'))
import myPackage2Code
I think I am doing something really wrong here, can someone point me a direction of how to handle import path within a self containing library?
Upvotes: 1
Views: 1176
Reputation: 50076
In your case, myLibrary
, myPackage1
and myPackage2
are packages. To import modules (or packages) from other packages, you must either use an absolute or relative path:
# in myPackage1Code.py
# absolute import
from myLibrary.myPackage2 import myPackage2Code
# relative import
from ..myPackage2 import myPackage2Code
This uniquely identifies the module you actually want, and tells Python where to find it. Note that .
and ..
are not file-system operations: they also work with dynamically composed namespace packages.
If you want to execute a script contained inside your package, you execute it as part of the package:
python2 -m myLibrary.myPackage1.myPackage1Code
Python2 also has implicit relative imports:
# in myLibrary/__init__.py
from myPackage2 import myPackage2Code
This form is generally discouraged, as it breaks if there is a global myPackage2
. It also does not work with Python3.
Note that for packages to work, you have to use them as such! If you directly access part of a package (don't do this at home!)
# directly run code module of a package in the shell
python2 myLibrary/myPackage1/myPackage1Code.py
# directly import module of a package
sys.path.append(os.path.abspath('../../myLibrary/myPackage2/'))
import myPackage2Code
then Python does not know that myPackage2Code
belongs to myLibrary.myPackage2
.
This has two notable effects:
myPackage2Code
cannot use relative imports. Python considers it a top-level module, so imports cannot go "up" in the package hierarchy.myPackage2Code
and myLibrary.myPackage2.myPackage2Code
. Since these contain separate objects, they for example fail isinstance
checks of except
clauses.Upvotes: 2