Loading classes from modules with reflection in Python (imp module)
For a dynamic language, it’s more difficult than it needs to be to import a module dynamically in Python. It’s very easy to just from foo import bar
, but what if you want to load a list of things and all you have is a string representation of each one, for example foo.bar
?
One use case for this is for configuration. Django uses this pattern to initialize apps via its INSTALLED_APPS
setting. For example, the default settings looks like this:
At some point, Django does the equivalent of a from django.contrib import admin
and then starts poking around for urls
and models
modules. I’m guessing this is done primarily to avoid circular import issues; if Django imports your apps as normal, but your apps turn around and import Django, then you’ve got a problem.
I wanted to reproduce this pattern myself, and it was a little harder than I expected. Python provides an imp for just this occasion. But, from the docs:
This function does not handle hierarchical module names (names containing dots). In order to find P.M, that is, submodule M of package P, use find_module() and load_module() to find and load package P, and then use find_module() with the path argument set to P.path. When P itself has a dotted name, apply this recipe recursively.
So, it’s basically is a pain the balls to deal with. Here is a working example:
And the output as expected:
Here is a directory listing of my test modules, in case this isn’t clear.