- Absolute and Relative Imports in Python
- Working of import in Python
- PEP 328 – Imports: Multi-Line and Absolute/Relative
- Timeline
- Rationale for Parentheses
- Rationale for Absolute Imports
- Rationale for Relative Imports
- Guido’s Decision
- Relative Imports and __name__
- Relative Imports and Indirection Entries in sys.modules
- References
- Copyright
Absolute and Relative Imports in Python
In this article, we are going to see that absolute and relative imports in Python.
Working of import in Python
Import in Python is similar to #include header_file in C/C++. Python modules can get access to code from another module by importing the file/function using import. The import statement is the most common way of invoking the import machinery, but it is not the only way. Import statement consists of the import keyword along with the name of the module. The import statement involves two operations, it searches for a module and it binds the result of the search to a name in the local scope. When a module is imported, Python runs all of the code in the module file and made available to the importer file. When a module is imported the interpreter first searches it in sys.modules, which is the cache of all modules which have been previously imported. If it is not found then it searches in all built-in modules with that name, if it is found then the interpreter runs all of the code and is made available to the file. If the module is not found then it searches for a file with the same name in the list of directories given by the variable sys.path. sys.path is a variable containing a list of paths that contains python libraries, packages, and a directory containing the input script. For example, a module named math is imported then the interpreter searches it in built-in modules, if it is not found then it searches for a file named math.py in list of directories given by sys.path.
PEP 328 – Imports: Multi-Line and Absolute/Relative
For the first problem, it is proposed that parentheses be permitted to enclose multiple names, thus allowing Python’s standard mechanisms for multi-line values to apply. For the second problem, it is proposed that all import statements be absolute by default (searching sys.path only) with special syntax (leading dots) for accessing package-relative imports.
Timeline
In Python 2.5, you must enable the new absolute import behavior with
from __future__ import absolute_import
You may use relative imports freely. In Python 2.6, any import statement that results in an intra-package import will raise DeprecationWarning (this also applies to from <> import that fails to use the relative import syntax).
Rationale for Parentheses
Currently, if you want to import a lot of names from a module or package, you have to choose one of several unpalatable options:
- Write a long line with backslash continuations:
from Tkinter import Tk, Frame, Button, Entry, Canvas, Text, \ LEFT, DISABLED, NORMAL, RIDGE, END
from Tkinter import Tk, Frame, Button, Entry, Canvas, Text from Tkinter import LEFT, DISABLED, NORMAL, RIDGE, END
Instead, it should be possible to use Python’s standard grouping mechanism (parentheses) to write the import statement:
from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text, LEFT, DISABLED, NORMAL, RIDGE, END)
This part of the proposal had BDFL approval from the beginning.
Parentheses support was added to Python 2.4.
Rationale for Absolute Imports
In Python 2.4 and earlier, if you’re reading a module located inside a package, it is not clear whether
refers to a top-level module or to another module inside the package. As Python’s library expands, more and more existing package internal modules suddenly shadow standard library modules by accident. It’s a particularly difficult problem inside packages because there’s no way to specify which module is meant. To resolve the ambiguity, it is proposed that foo will always be a module or package reachable from sys.path . This is called an absolute import.
The python-dev community chose absolute imports as the default because they’re the more common use case and because absolute imports can provide all the functionality of relative (intra-package) imports – albeit at the cost of difficulty when renaming package pieces higher up in the hierarchy or when moving one package inside another.
Because this represents a change in semantics, absolute imports will be optional in Python 2.5 and 2.6 through the use of
from __future__ import absolute_import
This part of the proposal had BDFL approval from the beginning.
Rationale for Relative Imports
With the shift to absolute imports, the question arose whether relative imports should be allowed at all. Several use cases were presented, the most important of which is being able to rearrange the structure of large packages without having to edit sub-packages. In addition, a module inside a package can’t easily import itself without relative imports.
Guido approved of the idea of relative imports, but there has been a lot of disagreement on the spelling (syntax). There does seem to be agreement that relative imports will require listing specific names to import (that is, import foo as a bare term will always be an absolute import).
These two forms have a couple of different suggested semantics. One semantic is to make each dot represent one level. There have been many complaints about the difficulty of counting dots. Another option is to only allow one level of relative import. That misses a lot of functionality, and people still complained about missing the dot in the one-dot form. The final option is to define an algorithm for finding relative modules and packages; the objection here is “Explicit is better than implicit”. (The algorithm proposed is “search up from current package directory until the ultimate package parent gets hit”.) Some people have suggested other punctuation as the separator, such as “-” or “^”. Some people have suggested using “*”:
from __pkg__.__pkg__ import
from .__parent__.__parent__ import
from MODULE import NAMES as RENAME searching HOW
import NAMES as RENAME from MODULE searching HOW [from NAMES] [in WHERE] import .
- What is the precise proposed syntax? (Which clauses are optional under which circumstances?)
- How strongly does the searching clause bind? In other words, do you write:
import foo as bar searching XXX, spam as ham searching XXX
import foo as bar, spam as ham searching XXX
Guido’s Decision
Guido has Pronounced [1] that relative imports will use leading dots. A single leading dot indicates a relative import, starting with the current package. Two or more leading dots give a relative import to the parent(s) of the current package, one level per dot after the first. Here’s a sample package layout:
package/ __init__.py subpackage1/ __init__.py moduleX.py moduleY.py subpackage2/ __init__.py moduleZ.py moduleA.py
Assuming that the current file is either moduleX.py or subpackage1/__init__.py , following are correct usages of the new syntax:
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
Note that while that last case is legal, it is certainly discouraged (“insane” was the word Guido used).
Relative imports must always use from <> import ; import <> is always absolute. Of course, absolute imports can use from <> import by omitting the leading dots. The reason import .foo is prohibited is because after
is usable in an expression. But
is not usable in an expression.
Relative Imports and __name__
Relative imports use a module’s __name__ attribute to determine that module’s position in the package hierarchy. If the module’s name does not contain any package information (e.g. it is set to ‘__main__’) then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.
Relative Imports and Indirection Entries in sys.modules
When packages were introduced, the concept of an indirection entry in sys.modules came into existence [2]. When an entry in sys.modules for a module within a package had a value of None, it represented that the module actually referenced the top-level module. For instance, ‘Sound.Effects.string’ might have a value of None in sys.modules. That meant any import that resolved to that name actually was to import the top-level ‘string’ module.
This introduced an optimization for when a relative import was meant to resolve to an absolute import. But since this PEP makes a very clear delineation between absolute and relative imports, this optimization is no longer needed. When absolute/relative imports become the only import semantics available then indirection entries in sys.modules will no longer be supported.
References
For more background, see the following python-dev threads:
Copyright
This document has been placed in the public domain.