Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
How do I import all the submodules of a Python namespace package?
What are Namespace Packages?
Namespace packages are a type of package in Python that allows you to split the sub-packages and modules within a single package across multiple, separate distribution packages. Unlike normal packages, the namespace packages don't require _init_.py file.
Automatically importing all submodules within a namespace package serves several purposes, like auto-registration without manually importing, and to load all available plugins in a system. This article discusses the two methods that you can use to import all the sub-modules of a Python namespace package -
Using pkgutil.iter_modules()
The pkgutil.iter_modules() is used to find and list the submodules and subpackages within a given package. It returns an iterator that has ModuleInfo objects, each containing information about a found module or package. The code below demonstrates how the pkgutil.iter_modules() is used to iterate through all modules -
import pkgutil
import importlib
import my_namespace_package
def import_submodules(package):
"""Import all submodules of a module, recursively."""
if isinstance(package, str):
package = importlib.import_module(package)
results = {}
for _, name, is_pkg in pkgutil.iter_modules(package.__path__, package.__name__ + '.'):
full_name = name
results[full_name] = importlib.import_module(full_name)
if is_pkg:
results.update(import_submodules(full_name))
return results
# Usage
modules = import_submodules('my_namespace_package')
The code above imports all submodules and subpackages of a given package and returns a dictionary where keys are module names and values are the actual imported module objects.
Using importlib.resources
The importlib.resources module allows Python's import system to access resources within a package. A resource is any readable object contained in the package. This is a modern approach and is effective for newer Python versions. The code below illustrates how importlib.resources is used to import all the submodules of a Python namespace package -
import importlib.resources
import importlib.util
import sys
import types
from pathlib import Path
def import_submodules_with_resources(package_name):
"""
Import all submodules using importlib.resources.files (Python 3.9+)
Args:
package_name: String name of the package
Returns:
Dictionary of imported modules
"""
results = {}
try:
# Get package as module first
package = importlib.import_module(package_name)
# Skip if not a package
if not isinstance(package, types.ModuleType) or not hasattr(package, '__path__'):
return results
# Use files() to get a traversable object (Python 3.9+)
package_path = importlib.resources.files(package_name)
# Process all items in the package
for item_path in package_path.iterdir():
# Handle Python modules
if item_path.is_file() and item_path.name.endswith('.py') and not item_path.name.startswith('__'):
module_name = f"{package_name}.{item_path.name[:-3]}"
try:
module = importlib.import_module(module_name)
results[module_name] = module
except ImportError as e:
print(f"Failed to import {module_name}: {e}")
# Handle potential subpackages
elif item_path.is_dir() and not item_path.name.startswith('__'):
subpackage_name = f"{package_name}.{item_path.name}"
# Use find_spec to check if it's a valid package
# This works for both regular and namespace packages
spec = importlib.util.find_spec(subpackage_name)
if spec is not None:
try:
subpackage = importlib.import_module(subpackage_name)
results[subpackage_name] = subpackage
# Recursively import submodules
sub_results = import_submodules_with_resources(subpackage_name)
results.update(sub_results)
except ImportError as e:
print(f"Failed to import {subpackage_name}: {e}")
except ModuleNotFoundError as e:
print(f"Package {package_name} not found: {e}")
except ImportError as e:
print(f"Error importing package {package_name}: {e}")
return results
The code above uses importlib.resources.files() to iterate over the contents in a given package. It returns a dictionary that maps fully qualified module names to their corresponding imported module objects.