Advanced Selective Import Strategies
Namespace Packages
Python supports the concept of namespace packages, which allow you to split a package's contents across multiple directories or even multiple repositories. This can be useful when working with large, complex projects or when collaborating with other developers.
To create a namespace package, you can use the __init__.py
file to define the package structure. Here's an example:
my_package/
__init__.py
module1.py
module2.py
subpackage/
__init__.py
module3.py
In this example, my_package
is a namespace package, and subpackage
is a subpackage within it. You can selectively import objects from these modules and subpackages using the familiar dot notation.
Relative Imports
When working with packages and modules, you may need to import objects from other modules within the same package. In this case, you can use relative imports, which allow you to reference modules based on their position relative to the current module.
## In module1.py
from . import module2
from .subpackage import module3
The .
represents the current package, and ..
represents the parent package. Relative imports can help you maintain a clear and organized code structure, especially when dealing with complex project hierarchies.
Absolute Imports
Alternatively, you can use absolute imports, which reference modules based on their full package path, starting from the top-level package. This approach is generally preferred for public-facing modules or when working with third-party packages.
## In main.py
from my_package.module1 import function_from_module1
from my_package.subpackage.module3 import class_from_module3
Absolute imports make your code more explicit and easier to understand, especially when working with large projects or collaborating with other developers.
Selective Importing with __all__
The __all__
special variable in a module can be used to control which objects are imported when using the from module_name import *
syntax. By defining __all__
in a module, you can specify a list of objects that should be imported when using the wildcard import.
## In module.py
__all__ = ['function1', 'class1']
def function1():
pass
def function2():
pass
class class1:
pass
class class2:
pass
Now, when you do from module import *
, only function1
and class1
will be imported, and function2
and class2
will be excluded.
This technique can help you maintain better control over your module's public API and prevent naming conflicts when using wildcard imports.