I'm currently working on a modular python framework. The current dilemma is, that one module has a set of submodules that have vastly different dependencies, and a user usually would only use one of those based on his choice. As I want to include examples for all, I also import those modules in some example files outside of the project structure.
The question I'm having is the following: Python will throw exceptions as for submodule_Y as some libraries are missing (and we do not want to install them). Is there a best way to avoid this issue?
my current approach in the __init__.py
of the parent module is the following:
try:
import submodule_Y
except:
pass
This is not good practice, so I was wondering what would be the optimal way to ignore exceptions if a certain submodule is not wanted by the user.
In the end I resorted to a utility function that handles imports with missing dependencies as follows:
import warnings
def optional_import(module_path:str, symbol_name: str) -> object:
"""
Handles optional imports if dependencies are not installed.
:param module_path: The module path to use for import.
:param symbol_name: The symbol name to import.
:returns: The imported symbol or a dummy object if an ImportError is raised.
"""
try:
module = __import__(module_path, fromlist=[symbol_name])
except ModuleNotFoundError as e:
warnings.warn(f"Could not import {symbol_name} from {module_path} due to {e}. Will use dummy object instead.", ImportWarning)
class Dummy:
"""A dummy class for imports that fail."""
def __init__(self, *args, **kwargs) -> None:
"""
Initialize the dummy class.
:param args: The args to pass to the class.
:param kwargs: The kwargs to pass to the class.
:raises ImportError: Always raised.
"""
raise ImportError(f"Could not import {symbol_name}, it requires {e.name} to be installed.")
return Dummy
return getattr(module, symbol_name)
This allows me to import submodules easily and get a warning if some dependencies are missing. If i then use the imported module and initialize Objects an ImportError
is raised.