9
votes

Choisissez l'adaptateur de manière dynamique en fonction de l'installation de Librarie (s)

Je concevons une bibliothèque disposant d'adaptateurs prenant en charge une large gamme de bibliothèques. Je souhaite que la bibliothèque choisit de manière dynamique de la même carte qui a la bibliothèque utilisée installée sur la machine lors de l'importation de classes spécifiques.

L'objectif est de pouvoir modifier la bibliothèque que le programme dépend sans avoir à modifier sans avoir à modifier code. Cette caractéristique particulière est destinée à la gestion des connexions de rabbbitmq, car nous avons eu beaucoup de problèmes avec PIKA , nous voulons être capable de changer dans une bibliothèque différente, par exemple pyampq ou rabbitpy sans avoir à changer le code sous-jacent.

Je pensais à mettre en œuvre quelque chose comme celui-ci dans le __ init __. py fichier de serviceLibrary.simple xxx

lorsque l'utilisateur importe la bibliothèque xxx

La couche sous-jacente ressemble à ceci

alternative.py xxx

synchronous.py xxx

ceci choisirait automatiquement le second lorsque Le premier n'est pas installé.

Y a-t-il un meilleur moyen de mettre en œuvre quelque chose comme ça? Si quelqu'un pouvait relier une bibliothèque / adaptateur avec une implémentation similaire qui serait utile également.

[EDIT]

Quel serait le moyen le plus propre mettre en œuvre quelque chose comme ça? À l'avenir, je voudrais également pouvoir modifier la préférence par défaut. En fin de compte, je peux simplement vous contenter d'utiliser la bibliothèque installée, comme je peux contrôler cela, mais ce serait une bonne fonctionnalité.

La suggestion d'Alexanders est intéressante, mais j'aimerais savoir s'il y a une manière plus propre.

[Edit2] L'exemple original a été simplifié. Chaque module peut contenir plusieurs types d'importations, par ex. Consommateur et éditeur.


1 commentaires

Regardez une architecture de composants, comme Zope.component, par exemple.


5 Réponses :


3
votes

Le ImportLIB.IMPORT_MODULE pourrait faire ce dont vous avez besoin: XXX

Je suppose que ce n'est pas la technique la plus avancée, mais l'idée devrait être claire. Et vous pouvez jeter un coup d'œil sur le Imp Module.


2 commentaires

Je pense que je peux toujours y aller, mais je veux voir s'il y a un moyen plus propre de la mise en œuvre. Bien que, avec cela, je pourrais changer la bibliothèque préférée en ajustant la liste qui est agréable.


J'ai posté ma version basée sur cela. Je suis assez content du résultat.



1
votes

Vous avez la bonne idée. Votre cas fonctionne car chaque subobject a le même genre de classes par exemple. Les deux API ont une classe appelée éditeur et vous pouvez simplement vous assurer que la version correcte est importée.

Si ce n'est pas vrai (si possible, la mise en œuvre A et B ne sont pas similaires) Vous écrivez votre propre Façade, qui n'est que votre propre API simple qui appelle ensuite la vraie API avec les méthodes / paramètres corrects pour cette bibliothèque.

Il est évident que la commutation entre les choix peut nécessiter des frais généraux (je ne connais pas votre cas, mais je ne connais pas votre cas, mais Par exemple, disons que vous aviez deux bibliothèques pour parcourir un fichier ouvert et la bibliothèque qui ouvre le fichier. Vous ne pouvez pas simplement passer à la deuxième bibliothèque au milieu du fichier et vous attendre à ce que la première bibliothèque s'est arrêtée ). Mais il s'agit simplement d'une question de sauver: xxx

etc.


1 commentaires

Merci d'avoir répondu. Je vais essayer de mettre en œuvre cela demain. Fondamentalement, les implémentations importées sont des couches que j'ai écrites pour vous assurer que, quelle que soit la bibliothèque utilisée, elle se comporte de même. Chaque éditeur aura donc exactement les mêmes variables, fonctions, etc.



1
votes

Je connais deux méthodes, on utilise sauvagement et une autre est ma supposition. Vous pouvez choisir un pour votre situation.

Le premier, qui est largement utilisé, tel que de tornado.concurrent import futur . xxx

alors vous pouvez utiliser de tornado.concurrent importation Future dans d'autres fichiers.

Le second, qui est mon devinière, et j'écris une démonstration simple, mais je ne l'ai pas utilisée dans l'environnement de production parce que je n'en ai pas besoin. < / p> xxx

Vous pouvez exécuter le script avant d'autres scripts importer servicelibrary.simple.simple.simple . Ensuite, vous pouvez utiliser le script comme avant: xxx

La seule chose que je me demande est que quelles sont les conséquences de mes devinations.


0 commentaires


1
votes

Basé sur les réponses que j'ai retrouvées avec la mise en œuvre suivante pour Python 2.7.

Les exemples sont simplifiés pour Stackoverflow. EM>. P>

import sys

PARENT = 'myservicelib.rabbitmq'
MODULES = ['test_adapter',
           'test_two_adapter']
SUCCESS = False

for _module in MODULES:
    try:
        __module_namespace = '{0}.{1}'.format(PARENT, _module)
        __import__(__module_namespace)
        __module = sys.modules[__module_namespace]
        Consumer = getattr(__module, 'Consumer')
        Publisher = getattr(__module, 'Publisher')
        SUCCESS = True
        break
    except ImportError:
        pass

if not SUCCESS:
    raise NotImplementedError('no supported rabbitmq library installed.')


1 commentaires

Il suffit de noter cela et voulait souligner que cela semble manquer de l'une des caractéristiques uniques de Python - la clause d'essai en essayant de faire des déclarations (BAH, aucun formatage de code dans des commentaires). "Sinon" en essayez d'être exécuté si aucune exception n'a été lancée, "sinon" pour se faire exécuter si aucune pause n'a été faite; Vous pouvez utiliser cela pour éliminer la variable de réussite.