Polymorphic imports

Chris Angelico rosuav at gmail.com
Tue Sep 21 15:10:02 EDT 2021


On Wed, Sep 22, 2021 at 4:59 AM Travis Griggs <travisgriggs at gmail.com> wrote:
>
> I guess this is kind of like mocking for testing. I have a simple module that's imported in a number of other spots in my program. There's a condition in the OS/filesystem where I'd like to import a polymorphically compatible variant of the same module. Can this be accomplished in a sort of once-and-only once spot?
>
> For example, consider something like this:
>
> client/
>   module_a
>   module_a_prime
> lib/
>   paths
>    lib_a
>    lib_b
>    ...
> model/
>   model_a
>   model_b
>   ...
> top_level_a
> top_level_b
> ...
>
>
> I have a number of imports of module_a. I have a paths module that isolates all of my file system access, and that's where the determination can be made which one to use, so I tried to do something like:
>
> def dynamic_client_module():
>    return client.module_a_prime if the_condition_occurs else client.module_a
>
>
> Hoping that I could do something like
>
> from lib import paths
> import paths.dynamic_client_module()
>
> But this seems to not work. Import can only take real modules? Not programatic ones?
>
> Is there a Not-Too-Evil-Way(tm) to add a level of programmatic indirection in the import declarations? Or some other trick from a different angle?

You can dynamically import modules using importlib.import_module(),
but an easier way might just be a conditional import:

# client/__init__.py
if some_condition:
    import module_a_default as module_a
else:
    import module_a_prime as module_a

Now everything that refers to client.module_a.whatever will get the
appropriate one, either the original or the alternate.

Alternatively, since you are talking about paths, it might be easiest
to give everything the same name, and then use sys.path to control
your import directories. Not sure which would work out best.

ChrisA


More information about the Python-list mailing list