Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
245 views
in Technique[技术] by (71.8m points)

python - Choose adapter dynamically depending on librarie(s) installed

I am designing a library that has adapters that supports a wide-range of libraries. I want the library to dynamically choose which ever adapter that has the library it uses installed on the machine when importing specific classes.

The goal is to be able to change the library that the program depends on without having to make modifications to the code. This particular feature is for handling RabbitMQ connections, as we have had a lot of problems with pika, we want to be able to change to a different library e.g. pyAMPQ or rabbitpy without having to change the underlying code.

I was thinking of implementing something like this in the __init__.py file of servicelibrary.simple.

try:
    #import pika # Is pika installed?
    from servicelibrary.simple.synchronous import Publisher
    from servicelibrary.simple.synchronous import Consumer
except ImportError:
    #import ampq # Is ampq installed?
    from servicelibrary.simple.alternative import Publisher
    from servicelibrary.simple.alternative import Consumer

Then when the user imports the library

from servicelibrary.simple import Publisher

The underlying layer looks something like this

alternative.py

import amqp

class Publisher(object):
    ......

class Consumer(object):
     ......    

synchronous.py

import pika

class Publisher(object):
    ......

class Consumer(object):
     ......   

This would automatically pick the second one when the first one is not installed.

Is there a better way of implementing something like this? If anyone could link a library/adapter with a similar implementation that would be helpful as well.

[Edit]

What would be the cleanest way to implement something like this? In the future I would also like to be able to change the default preference. Ultimately I may just settle for using the library installed, as I can control that, but it would be a nice feature to have.

Alexanders suggestion is interesting, but I would like to know if there is a cleaner way.

[Edit2]

The original example was simplified. Each module may contain multiple types of imports, e.g. Consumer and Publisher.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The importlib.import_module might do what you need:

INSTALLED = ['syncronous', 'alternative']  

for mod_name in INSTALLED:
    try: 
        module = importlib.import_module('servicelibrary.simple.' + mod_name)
        Publisher = getattr(module, 'Publisher')

        if Publisher:
            break  # found, what we needed

    except ImportError:
        continue

I guess, this is not the most advance technique, but the idea should be clear. And you can take a look at the imp module as well.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...