Changes in Import Statements in Python 3: Evolution of Relative and Star Imports

Dec 07, 2025 · Programming · 10 views · 7.8

Keywords: Python 3 | relative imports | star imports

Abstract: This article explores key changes in import statements in Python 3, focusing on the shift from implicit to explicit relative imports and restrictions on star import usage. Through detailed code examples and directory structures, it explains the design rationale behind these changes, including avoiding naming conflicts and improving code readability and maintainability. The article also discusses differences between Python 2 and Python 3, providing practical migration advice.

Introduction

Python 3 introduced significant improvements to the module import mechanism, primarily in relative imports and star imports. According to PEP 0404, Python 3 no longer supports implicit relative imports within packages, allowing only absolute imports and explicit relative imports. Additionally, star imports (e.g., from x import *) are restricted to module-level code. These changes aim to address naming conflicts and readability issues present in Python 2. This article explains these concepts in detail, with practical examples illustrating their application and migration strategies.

Relative Imports: Concept and Evolution

A relative import refers to importing a module relative to the current script or package location. In Python 2, developers could use implicit relative imports, but this could lead to ambiguity. Consider the following directory structure:

mypkg
├── base.py
└── derived.py

In derived.py, if importing the BaseThing class from base.py, Python 2 allowed:

from base import BaseThing

However, this implicit approach had potential issues. If a third-party package named base was installed system-wide, the interpreter might incorrectly import that package instead of the local base.py module, causing naming conflicts and unpredictable behavior.

Python 3 resolves this by introducing explicit relative imports. In derived.py, the correct import becomes:

from .base import BaseThing

The dot (.) indicates importing the base module from the current module's directory, equivalent to the path ./base.py. Similarly, double dots (..) move up one directory level, e.g., from ..mod import something corresponds to ../mod.py. Triple dots (...) move up two levels. Note that these paths are relative to the current module file's location, not the current working directory.

Restrictions on Star Imports

Star imports allow importing all public names from a module at once, but their usage is more restricted in Python 3. In Python 2, star imports could be used inside functions, for example:

def sin_degrees(x):
    from math import *
    return sin(degrees(x))

Although permitted in Python 2, this triggers a syntax warning: SyntaxWarning: import * only allowed at module level. Using star imports in local scopes can lead to namespace pollution and debugging difficulties.

Python 3 completely prohibits star imports in non-module-level code. Developers must adopt more explicit import methods. For instance, the above function can be rewritten as:

def sin_degrees(x):
    from math import sin, degrees
    return sin(degrees(x))

Or by moving the import to the module level:

from math import *

def sin_degrees(x):
    return sin(degrees(x))

This restriction enhances code clarity and maintainability, preventing errors caused by implicit imports.

Design Rationale and Migration Recommendations

The changes to import statements in Python 3 reflect a design shift towards greater explicitness and safety. Explicit relative imports eliminate ambiguity in intra-package imports, ensuring accurate module paths. Restrictions on star imports encourage developers to specify required names explicitly, reducing the risk of naming conflicts.

For projects migrating from Python 2 to Python 3, the following steps are recommended:

  1. Review all relative import statements, converting implicit imports to explicit forms (e.g., change from base import X to from .base import X).
  2. Audit star import usage to ensure they appear only at the module level, or replace them with specific name imports.
  3. Use tools like 2to3 or futurize to assist migration, but manually verify critical changes.

These adjustments not only aid compatibility but also improve overall code quality.

Conclusion

The modifications to import statements in Python 3, including the explicitness of relative imports and scope restrictions on star imports, represent significant steps in the language's evolution. By enhancing code clarity and safety, these changes support the development of larger and more complex projects. Developers should deeply understand these mechanisms and adhere to best practices in coding to fully leverage the advantages of Python 3.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.