Python Imports Style: Order, Grouping, Absolute vs Relative and Wildcards

The import block is the first thing a reader sees in a module, and it tells them what the code depends on. PEP 8's rules for it are short and almost entirely mechanical, which is why they are among the easiest to automate.
One module per line
PEP 8 asks for imports "on separate lines":
import sys, os
import os
import sys
from subprocess import PIPE, Popen
Importing several names from one module on a single line is explicitly allowed. The rule is about readability and diffs: removing os later changes one line instead of editing a list. pycodestyle reports the first form as E401 (multiple imports on one line).
At the top of the file, in a fixed order
Imports "are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants". The expected layout of a module's head is:
"""Export invoices as CSV files."""
from __future__ import annotations
__all__ = ["export_invoices"]
__version__ = "1.2"
import csv
import datetime as dt
from pathlib import Path
import requests
from billing.models import Invoice
from billing.utils import money
A few points from PEP 8 are visible here:
from __future__imports must come first after the docstring; this is a language requirement, not a style choice.- Module-level "dunder" names such as
__all__and__version__come after the docstring and the future imports, but before the other imports. - The three groups are separated by single blank lines: standard library (
csv,datetime,pathlib), related third-party packages (requests), and local application or library imports (billing).
pycodestyle reports an import that appears at module level after other code as E402 (module level import not at top of file). It tolerates a docstring, dunder assignments and conditional blocks such as try/except ImportError before imports, and it does not complain about imports inside functions, which PEP 8 does not forbid. Local imports are a legitimate tool for breaking an import cycle or delaying an expensive import until it is needed, though they also hide a dependency from the top of the module.
Absolute or relative?
PEP 8 recommends absolute imports because "they are usually more readable and tend to be better behaved (or at least give better error messages)" when the import system is misconfigured. Inside a package, explicit relative imports are "an acceptable alternative", especially in deep package layouts where absolute paths become verbose:
# Absolute
from billing.models import Invoice
# Explicit relative, from a module inside the billing package
from .models import Invoice
from . import utils
The standard library itself always uses absolute imports. Implicit relative imports, where import models silently meant a sibling module, were removed in Python 3 following PEP 328; the leading dot is now required.
When importing a class, from myclass import MyClass is usually fine. If that causes a name clash, import the module and qualify the name: import myclass, then myclass.MyClass. The same applies to modules whose names are clearer with their prefix, such as datetime.date versus a local date variable.
Wildcard imports
from module import * should be avoided, PEP 8 says, because it makes it "unclear which names are present in the namespace, confusing both readers and many automated tools". A linter cannot tell whether a name is defined or misspelled when a wildcard might have provided it; pyflakes, and therefore flake8 and ruff, report undefined names that may come from a star import as F405.
The guide allows one defensible use: republishing an internal interface as part of a public API, for example when an optional accelerated module replaces pure-Python definitions. In that case, the module being star-imported should define __all__, which controls exactly what import * exports.
Sorting imports automatically
PEP 8 defines the three groups but says nothing about the order inside each group. Tools fill that gap, usually by sorting alphabetically, with plain import x statements and from x import y statements arranged according to their settings. The two common choices are isort, a dedicated import sorter, and ruff, whose I rules reimplement isort's behaviour. Given this unsorted block:
import sys, os
import requests
from myapp.models import Invoice
import json
running ruff check --select I,E401 --fix produced:
import json
import os
import sys
import requests
from myapp.models import Invoice
Notice that myapp ended up in the third-party group. The tool cannot know which top-level packages are yours unless it is told, either by detecting your project's source directory or through a setting such as isort's known_first_party (also available in ruff's isort options). If imports keep landing in the wrong group, that setting is usually the cause.
When using isort alongside black, its documentation provides a black profile so that the two tools agree on line wrapping. Our article on ruff covers configuring import sorting there.
Imports and type checking
Type hints add one more pattern. A module that is only needed for annotations, and would create an import cycle at runtime, can be imported under if TYPE_CHECKING:, a constant from the typing module that is false at runtime and treated as true by type checkers. Combined with from __future__ import annotations or, from Python 3.14, the default deferred evaluation of annotations, this keeps the runtime import graph small. Use it sparingly: it is a fix for cycles and expensive imports, not a default.
Checklist
- Docstring first, then
from __future__imports, then dunders, then imports. - One module per
importline; group standard library, third party, local. - Absolute imports by default; explicit relative imports inside large packages.
- No wildcard imports, except to re-export with a defined
__all__. - Let a tool sort the block, and tell it which packages are first-party.
The checker on our home page reports E401 and E402. For the rest of the guide, start with our section-by-section overview of PEP 8.
Sources
- PEP 8, "Imports" and "Module Level Dunder Names".
- PEP 328 – Imports: Multi-Line and Absolute/Relative.
- Python Language Reference, "The import system";
typing.TYPE_CHECKINGin the typing module documentation. - isort documentation (profiles,
known_first_party); ruff rules reference (I001, E401, F405). Output above produced with ruff 0.16.
PEP 8, section by sectionPEP 8, explained section by section
What the official Python style guide actually says, section by section, which parts tools can check, and where it tells you to use your judgment.
Linters & formattersRuff: linter and formatter
One tool for linting, import sorting and formatting: how ruff's rule codes work, how to choose them, and what its fixes will and will not change.
PEP 8, section by sectionPEP 8 programming recommendations
Why `is None` beats `== None`, why bare `except:` is risky and why a lambda should not get a name: the habits at the end of PEP 8, with tested examples.