---
title: Never Use Wildcard Imports
impact: HIGH
impactDescription: Wildcard imports pollute the namespace, make it impossible to trace where a name comes from, and can silently override existing names, causing hard-to-debug subtle bugs.
tags: python, imports, namespace, quality, readability
---

## Never Use Wildcard Imports

`from module import *` imports every public name from a module into the current namespace. This:
- Makes it impossible to know where any name is defined without reading the imported module
- Can silently override names from prior imports or `builtins`
- Prevents static analysis tools from detecting undefined names
- Breaks auto-complete and go-to-definition in IDEs

The only acceptable use of `import *` is in a package's `__init__.py` to re-export a curated public API defined in `__all__`.

**Incorrect:**
```python
from os.path import *      # which names are now in scope?
from numpy import *        # overrides Python's built-in sum, any, all, etc.
from models import *       # User? Order? both? neither?
from utils import *

# Now these silently shadow built-ins:
result = sum([1, 2, 3])    # which sum? Python's or numpy's?
```

**Correct:**
```python
import os
from os import path as osp                    # or use pathlib
from pathlib import Path
import numpy as np                            # conventional alias
from models import User, Order, Product       # explicit names
from utils import format_date, validate_email

# Clear provenance for every name
result = np.sum([1, 2, 3])
full_path = Path("/data") / "file.txt"
```

**Acceptable use in `__init__.py`:**
```python
# package/__init__.py — re-export public API
from .client import Client
from .exceptions import APIError, RateLimitError

__all__ = ["Client", "APIError", "RateLimitError"]
```

**Tools:** Ruff `F403` (undefined-local-with-import-star), `W0401` in Pylint (wildcard-import), flake8, isort
