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
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
Cons
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__`.