Python Language Incompatibilities moving from Python 2 to Python 3 Absolute/Relative Imports

Help us to keep this website almost Ad Free! It takes only 10 seconds of your time:
> Step 1: Go view our video on YouTube: EF Core Bulk Extensions
> Step 2: And Like the video. BONUS: You can also share it!

Example

In Python 3, PEP 404 changes the way imports work from Python 2. Implicit relative imports are no longer allowed in packages and from ... import * imports are only allowed in module level code.

To achieve Python 3 behavior in Python 2:

  • the absolute imports feature can be enabled with from __future__ import absolute_import
  • explicit relative imports are encouraged in place of implicit relative imports

For clarification, in Python 2, a module can import the contents of another module located in the same directory as follows:

import foo

Notice the location of foo is ambiguous from the import statement alone. This type of implicit relative import is thus discouraged in favor of explicit relative imports, which look like the following:

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
from ...package import bar
from ...sys import path

The dot . allows an explicit declaration of the module location within the directory tree.


More on Relative Imports

Consider some user defined package called shapes. The directory structure is as follows:

shapes
├── __init__.py
|
├── circle.py
|
├── square.py
|
└── triangle.py

circle.py, square.py and triangle.py all import util.py as a module. How will they refer to a module in the same level?

 from . import util # use util.PI, util.sq(x), etc

OR

 from .util import * #use PI, sq(x), etc to call functions

The . is used for same-level relative imports.

Now, consider an alternate layout of the shapes module:

shapes
├── __init__.py
|
├── circle
│   ├── __init__.py
│   └── circle.py
|
├── square
│   ├── __init__.py
│   └── square.py
|
├── triangle
│   ├── __init__.py
│   ├── triangle.py
|
└── util.py

Now, how will these 3 classes refer to util.py?

 from .. import util # use util.PI, util.sq(x), etc

OR

 from ..util import * # use PI, sq(x), etc to call functions

The .. is used for parent-level relative imports. Add more .s with number of levels between the parent and child.



Got any Python Language Question?