PEP 842 proposes __export__ for controlled module visibility in Python
PEP 842 introduces a new standard for Python modules, proposing an `__export__` variable to explicitly define and limit the visibility of module members. This aims to improve code maintainability and prevent accidental reliance on internal implementation details, a common issue with current underscore-based conventions. If adopted, this PEP would affect all Python developers writing or consuming modules, providing a more robust mechanism for defining public APIs and enhancing the clarity of module interfaces. The proposal is currently in the Draft status for Python 3.16.
- →Introduce __export__ variable for module member control
- →Improve module API clarity and maintainability
- →__export__ affects attribute access and __dir__ behavior
- →Implicit __all__ definition from __export__
- →Interaction with module __getattr__ and lazy imports
Features (1) ›
- Introduce __export__ variable for module member control
This PEP proposes the introduction of an `__export__` variable within Python modules. Modules can define this variable, typically a list or tuple of strings, to explicitly declare which members (variables, classes, functions) are intended for external access. Any member not listed in `__export__` will raise an `ImportError` when accessed from outside the module, effectively limiting visibility and preventing accidental use of internal components.
Enhancements (1) ›
- Improve module API clarity and maintainability
The motivation behind `__export__` is to address the ambiguity of private names (often denoted by underscores) and the difficulties in managing imported module visibility. By requiring explicit export, developers can clearly distinguish between public and internal APIs, reducing the risk of breaking changes for users and decreasing the mental overhead associated with prefixing names.
Notes (3) ›
- __export__ affects attribute access and __dir__ behavior
When `__export__` is defined, all module attribute accesses will be filtered against it, raising `ImportError` for unexported names. Additionally, the module's `__dir__()` function will be modified to exclude unexported names, unless a custom `__dir__` is defined. Dunder names (`__name__`, `__dict__`, etc.) remain accessible regardless of `__export__`.
- Implicit __all__ definition from __export__
If a module defines `__export__` but not `__all__`, the `__all__` variable will be implicitly set to the contents of `__export__`. This ensures that wildcard imports (`from module import *`) will only import the explicitly exported members, further enforcing module API boundaries.
- Interaction with module __getattr__ and lazy imports
The behavior of `__export__` is not overridden by a module's `__getattr__()` function, as `__getattr__` is only invoked for names not already defined. Furthermore, lazy imports not listed in `__export__` will not be resolved when accessed outside the module, maintaining their lazy state.
https://peps.python.org/pep-0842/
Related releases
- crewAI 1.15.10 Patch Release CrewAI Releases ·
- LangGraph checkpoint-postgres 3.1.1 update LangGraph Releases ·
- LangGraph checkpoint-sqlite 3.1.1 released LangGraph Releases ·
- adk-python adds async non-blocking tool support Google ADK (Python) Releases ·
- Google ADK Python v2.6.0 adds features, fixes Google ADK (Python) Releases ·
- crewAI 1.15.9: Improved Tool Failure Reporting and Flow Events CrewAI Releases ·