Reputation: 395
I have a python package directory like this:
proj/
mod_a/
__init__.py
x.py
submod_x/
__init__.py
y.py
mod_b/
__init__.py
z.py
with x.py:
import submod_x.y
z.py:
import sys, os.path
sys.path.append(os.path.abspath('../'))
import mod_a.x
Now when I run:
$ python2 z.py
I get the things done coded in y.py
But when I run:
$ python3 z.py
I got an exception:
Traceback (most recent call last):
File "z.py", line 4, in <module>
import mod_a.x
File ".../proj/mod_a/x.py", line 1, in <module>
import submod_x.y
ImportError: No module named 'submod_x'
I wonder what differences between Python 2 and Python 3 when importing a package, and how can I import a package located in its parent directory using absolute import in Python 3?
Upvotes: 5
Views: 7972
Reputation: 395
Thanks for User's help. After reading PEP carefully I am able to answer the question myself now.
Firstly, there are 3 kinds of imports that I need to know:
Absolute imports.
import sys
Here, "sys" is a module or package name reachable from sys.path($PATH). Python inserts the directory where the script lies to sys.path by default. In other words, if I run python3 mod_b/z.py
under proj/
, python will insert proj/mod_b/
to sys.path.
Explicit relative imports.
from ..mod_a import x
Imports a module relative to current module(possibly not current working directory $PWD). The rationale is quite clearly described in python3 doc. And there are some examples from PEP-0328.
Attention: explicit relative imports must always use from <> import <>
.
Implicit relative imports.
import submod_x.y
In python2, such an import statement will lead to an import relative to current module implicitly. i.e. If I run python2 mod_a/x.py
under proj/
, the current module is x
, and the module submod_x.y
relative to x
will be correctly imported. The statement from submod_x import y
is equivalent to from .submod_x import y
as the explicit relative imports mentioned above.
However, it is obvious that implicit relative imports may be confused with absolute imports, as mentioned in PEP-0328. According to PEP-0404, python3 no longer supports implicit relative imports.
Secondly, running a scripts inside a package is seen an antipattern as Guido in an email...
I'm -1 on this and on any other proposed twiddlings of the main machinery. The only use case seems to be running scripts that happen to be living inside a module's directory, which I've always seen as an antipattern. To make me change my mind you'd have to convince me that it isn't.
It may cause explicit relative imports work improperly as you think. If you are intended to do such, refer the posts in the link above for solutions.
Here are some others' posts that may help you:
Changes in import statement python3
Import a module from a relative path
Upvotes: 4
Reputation: 14893
I think you should do this in x.py:
import mod_a.submod_x.y
Absolute imports from file locations are done with the absolute module name or like this:
from . import submod_x.y
Upvotes: 0