Introduction
Every Python module exposes a public interface — the set of names that other code should use. Without explicit control, consumers may depend on internal implementation details, making refactoring dangerous. The __all__ variable is Python's built-in mechanism for declaring a module's public API.
Key Concepts
__all__: A list of strings defining which names are exported byfrom module import *.- Underscore convention: Names starting with
_are considered private by convention, but are still importable. - Star import filtering: Only names in
__all__are included in wildcard imports. - Direct imports are unaffected:
from module import _private_funcalways works, regardless of__all__.
Real World Context
Libraries like requests, flask, and pandas all use __all__ to curate their public surface. When you type from requests import *, you get exactly the names the library authors intended — get, post, Session, etc. — not internal helpers like _internal_utils. This is critical for libraries with hundreds of internal functions that should never be called directly.
Deep Dive
Defining __all__
python# mylib/utils.py __all__ = ['PublicClass', 'public_func'] class PublicClass: """Part of the public API.""" pass def public_func() -> str: """Part of the public API.""" return _helper() class _PrivateClass: """Not exported via star import.""" pass def _helper() -> str: """Internal implementation detail.""" return "internal"
How star imports work
python# Without __all__: imports everything without leading underscore from mylib.utils import * # PublicClass, public_func are available # _PrivateClass, _helper are NOT (underscore convention) # With __all__: imports ONLY what's listed from mylib.utils import * # PublicClass, public_func are available # Even non-underscore names not in __all__ would be excluded
Combining __all__ with ABCs
Abstract Base Classes (abc.ABC) enforce interface contracts at the class level. Combined with __all__, you can expose clean interfaces while hiding implementation:
pythonfrom abc import ABC, abstractmethod __all__ = ['Stream'] class Stream(ABC): @abstractmethod def read(self) -> bytes: """Read data from the stream.""" ... @abstractmethod def write(self, data: bytes) -> int: """Write data to the stream.""" ...
Common Pitfalls
- Forgetting to update
__all__: When you add a new public function, you must also add it to__all__. Linters likepylintcan warn about this. - Relying solely on underscores: The underscore convention is just a convention — it does not prevent imports. Use
__all__for enforceable API boundaries. - Putting too much in
__all__: Only export what consumers genuinely need. A smaller public API is easier to maintain and version.
Best Practices
- Always define
__all__in library modules, especially__init__.pyfiles. - Keep
__all__at the top of the file, right after imports, so it serves as a quick reference. - Use
_prefix for internal helpers as a secondary signal alongside__all__. - Run
pyflakesorruffto detect names in__all__that do not exist in the module.
Summary
__all__ is the standard mechanism for declaring a module's public API. It controls from module import * behavior, acts as documentation for consumers, and helps tools enforce API boundaries. Combined with the underscore convention and ABCs, it provides a robust approach to interface design in Python.
Code Examples
# analytics/__init__.py
__all__ = ['track_event', 'get_metrics']
from ._tracker import track_event
from ._metrics import get_metrics
from ._internal import _flush_buffer # NOT in __all__
# Consumer code
from analytics import *
track_event('signup') # Works
get_metrics() # Works
# _flush_buffer # NameError if only star-importedfrom abc import ABC, abstractmethod
__all__ = ['Stream']
class Stream(ABC):
@abstractmethod
def read(self) -> bytes:
...
@abstractmethod
def write(self, data: bytes) -> int:
...
class _BufferedStream(Stream):
"""Internal implementation, not exported."""
def read(self) -> bytes:
return b'data'
def write(self, data: bytes) -> int:
return len(data)