Python > Modules and Packages > Packages > The `__all__` Variable in Packages

Controlling Package Imports with `__all__`

This snippet demonstrates how the `__all__` variable in a Python package's `__init__.py` file controls which modules and subpackages are imported when a user performs a `from package import *` statement. It is crucial for maintaining a clean and predictable API for your package.

Package Structure

First, let's establish the directory structure for our example package. We'll create a package called `my_package` with a couple of modules and a subpackage.

# Directory structure:
# my_package/
#     __init__.py
#     module_a.py
#     module_b.py
#     subpackage/
#         __init__.py
#         module_c.py

Module `module_a.py`

This is a simple module containing a function.

def function_a():
    return "Function A from module_a"

Module `module_b.py`

Another simple module containing a function.

def function_b():
    return "Function B from module_b"

Module `subpackage/module_c.py`

A module inside the subpackage, also containing a function.

def function_c():
    return "Function C from subpackage/module_c"

`__init__.py` without `__all__`

Here's the `__init__.py` file *without* the `__all__` variable. Note that simply importing the modules doesn't automatically expose them to `from my_package import *`. It only defines the name `init_function` in the package's namespace.

# my_package/__init__.py

import my_package.module_a
import my_package.module_b


def init_function():
    return "Package initialized!"

`__init__.py` *with* `__all__`

This is the key. The `__all__` variable is a list of strings that specify which module names should be imported when using `from my_package import *`. In this case, only `module_a` and `module_b` will be imported.

# my_package/__init__.py

import my_package.module_a
import my_package.module_b


def init_function():
    return "Package initialized!"

__all__ = ['module_a', 'module_b']

`__init__.py` *with* `__all__` including subpackage

In this version, we're including the `subpackage` in the `__all__` list. This means `from my_package import *` will also import the `subpackage` namespace.

# my_package/__init__.py

import my_package.module_a
import my_package.module_b
import my_package.subpackage


def init_function():
    return "Package initialized!"

__all__ = ['module_a', 'module_b', 'subpackage']

Usage Demonstration

This shows how to access the imported modules *after* using `from my_package import *`. If a module or subpackage is *not* listed in `__all__`, attempting to access it directly after the import statement will result in an `ImportError`.

import my_package

print(my_package.init_function())

from my_package import *

print(module_a.function_a())
print(module_b.function_b())
# The following line will raise an error because subpackage isn't included in __all__ in previous example
# print(subpackage.module_c.function_c())

Concepts Behind the Snippet

The `__all__` variable is a list of public objects (usually modules, subpackages, or variables) that you want to expose as part of your package's API. It controls what gets imported when a user uses `from my_package import *`. If `__all__` is not defined, `from my_package import *` imports all names that do not begin with an underscore ('_'). This behavior is generally discouraged because it can lead to unexpected namespace pollution and make it difficult for users to understand which names are part of your package's public API.

Real-Life Use Case

Imagine you're building a large library for scientific computing. You might have many internal helper modules that you don't want users to directly access. By using `__all__`, you can precisely control which modules are considered part of the public API, making your library easier to use and less prone to accidental misuse of internal functions.

Best Practices

  • Always define `__all__` in your package's `__init__.py` files to explicitly control your package's public API.
  • Keep `__all__` updated as you add, remove, or rename modules in your package.
  • Document the contents of `__all__` in your package's documentation so users know which modules are intended for public use.
  • Avoid using `from package import *` in production code. It can make it difficult to understand where names are coming from and can lead to namespace collisions. Explicitly import the names you need instead (e.g., `from my_package import module_a`).

Interview Tip

When asked about Python packages, be prepared to discuss the purpose of `__init__.py` files and the role of the `__all__` variable in controlling imports. Explain that `__all__` helps define the public API of a package and prevents namespace pollution when using wildcard imports. Demonstrating an understanding of these concepts shows good Python package design knowledge.

When to Use Them

Use `__all__` whenever you are creating a Python package that will be distributed and used by others. It's especially important for larger packages with many modules and subpackages.

Memory Footprint

The `__all__` variable itself doesn't directly impact memory footprint. However, by controlling which modules are imported with `from package import *`, you can indirectly influence memory usage. If you avoid importing unnecessary modules, you can reduce the initial memory footprint of your application.

Alternatives

The primary alternative to using `__all__` is to rely on the default behavior of `from package import *`, which imports all names that don't start with an underscore. However, this is generally not recommended, as it can lead to unexpected behavior and a less well-defined API. Another approach is to avoid using `from package import *` altogether and always explicitly import the names you need (e.g., `import my_package.module_a` and then refer to functions as `my_package.module_a.function_a()`).

Pros

  • Clear API: `__all__` clearly defines the public API of your package.
  • Namespace Control: Prevents unwanted names from being imported into the user's namespace.
  • Maintainability: Makes it easier to refactor your package without breaking existing code that relies on its public API.

Cons

  • Maintenance Overhead: You need to remember to update `__all__` whenever you add, remove, or rename modules in your package.
  • Potential for Errors: If you forget to include a module in `__all__`, users will not be able to import it using `from package import *`.

FAQ

  • What happens if I don't define `__all__` in my package's `__init__.py`?

    If `__all__` is not defined, `from package import *` will import all names defined in the package's namespace that do *not* begin with an underscore (`_`). This is generally not recommended because it can expose internal implementation details and lead to namespace pollution.
  • Can I include variables or functions defined directly in `__init__.py` in the `__all__` list?

    Yes, you can. `__all__` is a list of strings representing names in the package's namespace. This includes names of modules, subpackages, functions, classes, or any other objects defined directly within the `__init__.py` file.
  • How does `__all__` affect regular imports (e.g., `import my_package.module_a`)?

    The `__all__` variable only affects the behavior of `from package import *`. It has no impact on regular import statements like `import my_package.module_a`, which will always import the specified module regardless of whether it's included in `__all__`.