What is __all__ in Python?

Discover __all__ in Python: how to control module exports, manage imports with from module import *, and properly structure your packages.
9 min read
Believemy logo

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

PYTHON
# 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:

PYTHON
# === 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)
Good to know

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__

PYTHON
# 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

PYTHON
# === __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:

PYTHON
# 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

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:

PYTHON
# 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:

PYTHON
# 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:

PYTHON
# 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:

MechanismSyntaxEffect on import *Effect on explicit import
__all____all__ = ["name"]Only listed names are importedNo effect
Single underscore_nameExcluded (without __all__)No effect
Double underscore__nameExcluded (name mangling in classes)Accessible via _Class__name
Dunder__name__Included (without __all__)No effect
Good to know

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.

PYTHON
# ✅ 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:

PYTHON
"""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:

PYTHON
# ✅ 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:

PYTHON
# ❌ 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

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:

PYTHON
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:

PYTHON
# 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

Question

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.

 

Question

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.

 

Question

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.

 

Question

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.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.