Fundamentals 8 min read

Understanding Implicit and Explicit Relative Imports in Python Packages

This article explains Python's implicit and explicit relative import mechanisms, demonstrates directory structures, shows how to use __init__.py, and provides practical code examples illustrating import statements, common pitfalls, and best practices for managing package imports in larger projects.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Understanding Implicit and Explicit Relative Imports in Python Packages

The example starts with a package named mypackage that contains two sub‑modules a and b , each with its own __init__.py and a single Python file.

Using the tree command the directory layout looks like:

<code>$ tree
mypackage
|____ __init__.py
|___ a
|     |___ __init__.py
|     |___ bar.py
|____ b
      |___ __init__.py
      |____ foo.py</code>

File contents are simple constants:

<code>$ cat mypackage/a/bar.py
BAR = 1

$ cat mypackage/b/foo.py
FOO = 2</code>

These modules can be imported using Python's implicit relative import, which does not specify the relative location explicitly; the interpreter assumes the current module as the base:

<code>In [1]: import mypackage
In [2]: import mypackage.a
In [3]: import mypackage.a.bar</code>

Explicit relative imports use leading dots to indicate the current ( . ), parent ( .. ), or higher‑level packages ( ... ). For example, modifying bar.py to import FOO from b.foo looks like:

<code>BAR = 1
from ..b.foo import FOO</code>

Running the import shows the value is correctly resolved:

<code>In [1]: from mypackage.a.bar import FOO
In [2]: FOO
Out[2]: 2</code>

Two common relative‑import styles are demonstrated: from . import foo (relative to the current package) and from .foo import foo (relative to the current module). The choice affects how the imported name is accessed.

Placing imports in a package's __init__.py provides a convenient entry point. For example, mypackage/b/__init__.py can expose foo and FOO :

<code>from . import foo
from .foo import FOO</code>

Relative imports are especially useful in large projects with deep module hierarchies, improving maintainability and allowing package renaming without breaking internal imports.

Python 2 and Python 3 handle relative imports differently. In Python 2, relative imports must be placed inside code and cannot be executed directly, while Python 3 allows relative imports from the current directory but raises errors for non‑package contexts.

Using from __future__ import absolute_import disables implicit relative imports, forcing explicit syntax and preventing accidental shadowing of standard‑library modules (e.g., a local os.py ).

Wildcard imports ( from xxx import * ) are discouraged. Defining an __all__ list in __init__.py controls which names are exported, avoiding unintended namespace pollution.

<code># mymodule.py
__all__ = ['a']
a = 1
b = 2

# In a REPL
from mymodule import *
a  # -> 1
b  # NameError</code>
Modulepackageexplicit-importimplicit-importimport-managementrelative import
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.