Explain Codes LogoExplain Codes Logo

How to dynamically load a Python class

python
dynamic-import
importlib
python-best-practices
Nikita BarsukovbyNikita Barsukov·Sep 25, 2024
TLDR

Want to dynamically load a class in Python? Use __import__() for module loading and getattr() to extract the class. Try this:

module = __import__('module_name', globals(), locals(), ['object'], -1) MyClass = getattr(module, 'ClassName') instance = MyClass()

This code instantly loads ClassName from our module_name.py file. To create an instance use instance = MyClass().

Safer and cleaner: importlib

While __import__() is great, the importlib library often offers cleaner syntax:

import importlib module = importlib.import_module('module_name') MyClass = getattr(module, 'ClassName') instance = MyClass()

No rocket science, right?

Loading a class from a module path

For fully-qualified class names, split on the last dot to separate the module name and class name:

def my_import(name): """ Walks the walk, talks the talk, does the 'dynamic import' rock! """ module, _, cls = name.rpartition('.') mod = __import__(module, fromlist=[cls]) return getattr(mod, cls) MyClass = my_import('package.module.ClassName') instance = MyClass() # Performs inception. Not affiliated with Leonardo DiCaprio.

The importance of fromlist

As the old programmer proverb goes, "If thou forgets fromlist, thy code shall be forgetten". Ensure non-empty fromlist especially when you're on Google App Engine, which is a bit fussy.

module = __import__('module_name', fromlist=['ClassName'])

Failing gracefully

No class should go missing on your watch. If a module or class can't be found, consider using Python's error handling capabilities:

try { MyClass = my_import('my_never_seen_before_class') } except ImportError as e: print(f'Something bad happened during import, but we got it covered: {e}')

Best practices and pro tips

Master the art (and sometimes the dark art) of dynamic loading with these pro tips.

Google App Engine

Google App Engine doesn't play nice with all dependencies. Stick to native libraries and be mindful while using fromlist.

Avoid the constant string pain

Instead of leaving a trail of hardcoded strings, consider fetching class paths from configuration files or environment variables.

Django's import_string

The Django framework's import_string function can be handy. However, the more general-purpose importlib provides greater flexibility.

Check before you wreck

After dynamic loading, ensure your class instance works as expected. Catch TypeError during instantiation.