Definition of __all__ in Python
In Python, __all__ is a special variable defined at the module level. It is a list of strings that explicitly indicates which names (functions, classes, variables) should be exported when a user performs a from module import *. It is a fundamental mechanism for controlling the public interface of your modules and packages.
If you want to master Python in depth, including the structuring of professional projects, our complete Python course will guide you step by step through learning these essential concepts.
Without __all__, the from module import * statement imports all public names from the module, meaning all names that do not start with an underscore (_). By defining __all__, you take full control over what is exported, making your code more predictable and better organized.
Basic syntax and behavior
The syntax of __all__ is very simple: you just need to declare a list of strings at the beginning of your module, each string corresponding to the name of an object you want to make accessible via import *.
Basic declaration
# my_module.py
__all__ = ["public_function", "MyClass", "CONSTANT"]
def public_function():
"""This function will be exported."""
return "I am public"
def _private_function():
"""This function will not be exported (underscore)."""
return "I am private"
def helper_function():
"""This function will NOT be exported despite no underscore."""
return "I am an internal helper"
class MyClass:
"""This class will be exported."""
pass
class InternalClass:
"""This class will NOT be exported."""
pass
CONSTANT = 42
OTHER_VARIABLE = 100 # Not exported
In this example, only public_function, MyClass, and CONSTANT will be imported when another file executes from my_module import *. The elements helper_function, InternalClass, and OTHER_VARIABLE will not be included in the wildcard import, even though they do not start with an underscore.
Behavior with and without __all__
Here is a comparison to clearly understand the difference:
# === Without __all__ ===
# utils.py
def calculate():
pass
def _internal():
pass
def format_data():
pass
# from utils import * → imports: calculate, format_data
# (_internal is excluded because it starts with _)
# === With __all__ ===
# utils.py
__all__ = ["calculate"]
def calculate():
pass
def _internal():
pass
def format_data():
pass
# from utils import * → imports only: calculate
# (format_data is excluded even without underscore)
Important: __all__ does not prevent explicit imports. Even if format_data is not in __all__, you can still write from utils import format_data. The __all__ variable only controls the behavior of import *.
Usage in packages
One of the most powerful uses of __all__ is found in __init__.py files of Python packages. This allows you to define a clean public API for your entire package.
Package structure with __all__
# Package structure:
# my_package/
# ├── __init__.py
# ├── module_a.py
# ├── module_b.py
# └── _internal_module.py
# === module_a.py ===
__all__ = ["ClassA", "function_a"]
class ClassA:
def greet(self):
return "Hello from ClassA"
def function_a():
return "Result from function_a"
def _helper_a():
return "Internal helper"
# === module_b.py ===
__all__ = ["ClassB"]
class ClassB:
def calculate(self):
return 42
def internal_function_b():
return "Not exported"
Package __init__.py file
# === __init__.py ===
from .module_a import ClassA, function_a
from .module_b import ClassB
__all__ = ["ClassA", "function_a", "ClassB"]
Thanks to this configuration, a user of your package can simply write:
# Using the package
from my_package import *
# Only ClassA, function_a, and ClassB are available
obj = ClassA()
print(obj.greet()) # Hello from ClassA
print(function_a()) # Result from function_a
calc = ClassB()
print(calc.calculate()) # 42
Warning: If you do not define __all__ in an __init__.py file, the from package import * statement will not import anything at all (or only what is explicitly defined in __init__.py). This is a frequent source of confusion for beginners.
Advanced practical examples
Dynamic construction of __all__
You can build __all__ dynamically, which is particularly useful in large modules:
# api.py - Dynamic construction of __all__
import inspect
import sys
__all__ = []
def export(obj):
"""Decorator to mark a function/class as exported."""
__all__.append(obj.__name__)
return obj
@export
def create_user(name, email):
"""Creates a new user."""
return {"name": name, "email": email}
@export
def delete_user(user_id):
"""Deletes a user by their identifier."""
return f"User {user_id} deleted"
def _validate_email(email):
"""Internal validation function."""
return "@" in email
@export
class UserManager:
"""Main user management class."""
def __init__(self):
self.users = []
def add(self, user):
self.users.append(user)
# At this point, __all__ automatically contains:
# ["create_user", "delete_user", "UserManager"]
print(__all__)
This pattern with an @export decorator is elegant because it allows you to mark each element as public directly where it is defined, rather than maintaining a separate list at the top of the file.
__all__ with re-exports
A common case consists of re-exporting elements imported from other modules:
# library/__init__.py
# Controlled re-export from multiple submodules
from .connection import Connection, create_connection
from .queries import execute_query, SQLQuery
from .results import Result, format_result
from .exceptions import (
ConnectionError,
QueryError,
TimeoutError,
)
__all__ = [
# Connection
"Connection",
"create_connection",
# Queries
"execute_query",
"SQLQuery",
# Results
"Result",
"format_result",
# Exceptions
"ConnectionError",
"QueryError",
"TimeoutError",
]
This approach is very common in professional Python libraries. It allows you to provide a flat and intuitive API while maintaining a modular internal organization.
Verifying __all__ with linting tools
You can write a simple test to verify that all elements listed in __all__ actually exist in the module:
# test_exports.py
import my_module
def test_all_exports_exist():
"""Verifies that each name in __all__ exists in the module."""
for name in my_module.__all__:
assert hasattr(my_module, name), (
f"'{name}' is listed in __all__ but does not exist in the module"
)
def test_all_is_a_list():
"""Verifies that __all__ is indeed a list of strings."""
assert isinstance(my_module.__all__, list)
for element in my_module.__all__:
assert isinstance(element, str), (
f"Each element of __all__ must be a string, found: {type(element)}"
)
test_all_exports_exist()
test_all_is_a_list()
print("All tests pass!")
__all__ and other encapsulation mechanisms
It is important to understand how __all__ relates to other Python conventions for managing name visibility:
| Mechanism | Syntax | Effect on import * | Effect on explicit import |
|---|---|---|---|
__all__ | __all__ = ["name"] | Only listed names are imported | No effect |
| Single underscore | _name | Excluded (without __all__) | No effect |
| Double underscore | __name | Excluded (name mangling in classes) | Accessible via _Class__name |
| Dunder | __name__ | Included (without __all__) | No effect |
Good to know: When __all__ is defined, it has absolute priority. Even names starting with an underscore will be exported if they appear in the __all__ list. Conversely, a public name will be excluded if it is not listed there.
Best practices
Here are the essential recommendations for using __all__ effectively in your Python projects:
1. Always define __all__ in public modules
If your module is intended to be imported by other developers, systematically define __all__. This clearly documents the public API and prevents accidental leaks of internal elements.
# ✅ Good practice
__all__ = ["process_data", "validate_input", "DataForm"]
def process_data(data):
pass
def validate_input(entry):
pass
class DataForm:
pass
def _clean(text): # Internal
pass
2. Place __all__ at the top of the module
Always place __all__ right after the imports and the module's docstring. This allows anyone reading your code to immediately understand the public interface:
"""Payment management module."""
import json
from datetime import datetime
__all__ = [
"Payment",
"process_payment",
"refund",
"PaymentError",
]
# ... rest of the code
3. Use a list rather than a tuple
Although Python accepts a tuple for __all__, the convention is to use a list. This makes modification easier and stays consistent with PEP 8:
# ✅ Recommended: use a list
__all__ = ["element_a", "element_b", "element_c"]
# ❌ Less conventional: use a tuple
__all__ = ("element_a", "element_b", "element_c")
4. Keep __all__ synchronized
One of the most common pitfalls is adding a new public function to the module without updating __all__. Remember to regularly check consistency, or use the @export decorator pattern presented above.
5. Avoid import * in production code
Even though __all__ makes import * safer, prefer explicit imports in your production code:
# ❌ Avoid in production
from my_module import *
# ✅ Prefer explicit imports
from my_module import public_function, MyClass
The import * statement remains acceptable in __init__.py files to group package exports, or in interactive sessions and Jupyter notebooks.
Concrete use cases
Popular libraries using __all__
Many famous Python libraries use __all__ to structure their API. For example, if you look at the source code of os, json, or collections, you will find __all__ definitions. You can also inspect this variable directly:
import json
import os
# View the public exports of a module
print(json.__all__)
# ['dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder']
print(len(os.__all__)) # Number of elements exported by os
# Check if a module defines __all__
import math
print(hasattr(math, '__all__')) # False - math does not define __all__
Usage with type checkers
Tools like mypy and pyright use __all__ to determine the public symbols of a module. It is therefore important not only for runtime, but also for static code analysis:
# types_utils.py
from typing import TypeVar, Generic
__all__ = ["Identifier", "Container"]
T = TypeVar("T") # Not exported
type Identifier = int | str
class Container(Generic[T]):
def __init__(self, value: T) -> None:
self.value = value
def get(self) -> T:
return self.value
Frequently asked questions
What happens if __all__ contains a name that does not exist in the module?
Python will raise an AttributeError when a user executes from module import *. The unfound name will cause an explicit error. This is why it is crucial to keep __all__ synchronized with the actual content of the module. We recommend writing automated tests to verify this consistency.
Does __all__ affect the dir() function?
No, __all__ does not affect dir(). The len function or dir() applied to a module will always list all attributes of the module, whether they are in __all__ or not. The __all__ variable exclusively controls the behavior of from module import * and serves as documentation for static analysis tools.
Can you use __all__ in a main script?
Technically yes, but it has no practical use. The __all__ variable only makes sense in a module intended to be imported by other files. If your file is the main script (with if __name__ == "__main__"), no one will import * from it, so __all__ will simply be ignored.
How can you learn to properly structure your Python modules?
Module and package structuring is an essential skill for any Python developer. Understanding __all__, relative imports, __init__.py files, and naming conventions requires practice. Our dedicated Python course covers in detail the creation of clean modules, package management, and all the best practices for writing professional and maintainable code.