Python Wildcard Import: What `from module import *` Does
python wildcard import: Learn how Python wildcard imports resolve names, how __all__ controls the import surface, and when to avoid them in production code.
A wildcard import in Python—from module import *—copies every public name from another module into the current namespace. It is one of the most convenient import forms and also one of the most criticized. Understanding how a python wildcard import resolves names is the first step toward deciding when it is acceptable and when it creates maintainability problems.
How a Wildcard Import Resolves Names
When Python executes from module import *, it loads the module and then selects names based on a specific rule:
- If the module defines
__all__, only the names in that list are imported. - If
__all__is not defined, all names that do not start with an underscore are imported.
This means the wildcard does not literally import everything. It imports the module's public surface. Names like _helper or __version__ are excluded by default.
# math_utils.py def add(a, b): return a + b def subtract(a, b): return a - b _private_helper = 42
# main.py from math_utils import * print(add(1, 2)) # 3 print(subtract(5, 2)) # 3 print(_private_helper) # NameError: name '_private_helper' is not defined
The underscore-prefixed name never enters the importing namespace.
Controlling the Import Surface with __all__
__all__ gives the module author explicit control over what a wildcard import exposes. It is a list of strings placed at module level.
# math_utils.py __all__ = ["add", "subtract"] def add(a, b): return a + b def subtract(a, b): return a - b def multiply(a, b): return a * b
Now from math_utils import * imports only add and subtract, even though multiply exists without an underscore prefix. This is the recommended way to make a wildcard import predictable: the author decides the public API instead of leaving it to the underscore convention.
__all__ also applies when the target is a package. Defining __all__ in __init__.py controls what from package import * brings in, which is useful for flattening a package interface without exposing internal submodules.
Namespace Pollution and Shadowing
The most serious practical problem with wildcard imports is namespace pollution. When you import * from a module, you do not know exactly which names you are getting without reading that module's source. If two modules export the same name, the second import wins silently.
from utils import * from config import * # If both define "VERSION", the one from config wins. print(VERSION)
There is no error and no warning. The first module's VERSION is simply overwritten. This makes debugging confusing because the origin of a name depends on import order, which is easy to overlook during refactoring.
The same problem appears with builtins. If a module exports a name like list or id, a wildcard import shadows the builtin for the rest of the file. Code that worked before can break when a dependency adds a new public name that collides with something already in scope.
Performance and Import-Time Behavior
A wildcard import does not load a module faster than an explicit import. Python still executes the entire module to build its namespace. The difference is in what happens afterward: instead of binding one name to the module object, Python copies many names into the current namespace.
For a large module, this can mean hundreds of name bindings. The overhead is usually negligible compared with the module execution itself, so wildcard imports are not a performance optimization. If anything, they add a small amount of extra work.
A more relevant runtime concern is that wildcard imports bind names at the moment the statement executes. If the module is later reloaded or patched, the imported names do not update. An explicit import module keeps a reference to the module object, so attribute access reflects any changes made to that object.
When a Wildcard Import Is Acceptable
There are a few narrow cases where wildcard imports are conventional and reasonable:
- Interactive sessions and REPL exploration, where typing
import mathand thenmath.for every call becomes tedious. - Short scripts where the namespace stays small and the imported names are obvious from context.
- Package
__init__.pyfiles that deliberately re-export a public API, such asfrom .submodule import *to flatten the interface for consumers.
Even in these cases, the source module should define __all__ so the public surface is explicit and stable. Without __all__, a future rename or a new public function can silently change what the wildcard exposes.
Alternatives to Wildcard Imports
For production code, explicit imports are almost always the better choice:
from math_utils import add, subtract
This makes dependencies visible at the top of the file, avoids name collisions, and lets linters and static analyzers resolve every name. If a module exposes many public names, import the module itself and use attribute access:
import math_utils result = math_utils.add(1, 2)
This keeps the namespace clean and makes the source of every name explicit.
For re-exporting in __init__.py, combine explicit imports with __all__ instead of using a wildcard:
from .submodule import add, subtract __all__ = ["add", "subtract"]
Consumers get the same public API, and the module's own code remains explicit about where each name comes from.
Compatibility and Tooling Concerns
Wildcard imports interact poorly with several development tools. Linters such as flake8 and pyflakes flag them because they make undefined-name detection unreliable. Static type checkers like mypy and pyright have difficulty resolving names that arrive via a wildcard unless the source module defines __all__ with explicit types.
In a large codebase, this can hide real bugs. A typo in a name that should raise a NameError might silently resolve to a name imported from another module through a wildcard. The failure appears later, often at runtime, in a location far from the actual mistake.
The one place wildcard imports are explicitly supported and even encouraged is interactive work. In a module file, the cost in clarity and tooling support usually outweighs the convenience. If you do use a wildcard import in a committed file, make sure the source module defines __all__, keep the import at the top of the file, and verify that no imported name collides with names already in scope.