2010-03-09 2 views
3

J'ai un ensemble de fonctionnalités assez simple pour lequel j'ai plusieurs implémentations, par exemple, un magasin de données qui pourrait être supporté par Redis, MongoDB ou PostgreSQL. Comment dois-je structurer/écrire mon code pour que le code qui veut utiliser une de ces implémentations n'ait besoin que des dépendances pour cette implémentation, par exemple, ils n'ont pas besoin d'avoir psycopg2 installé s'ils utilisent le backend Redis.Comment ne payer que la pénalité de dépendance pour l'implémentation que vous utilisez en Python?

Voici un exemple. Supposons le module suivant, example.py.

class RedisExample(object): 
    try: 
     import redis 
    except ImportError: 
     print("You need to install redis-py.") 

    def __init__(self): 
     super(RedisExample, self).__init__() 

class UnsatisfiedExample(object): 
    try: 
     import flibbertigibbet 
    except ImportError: 
     print("You need to install flibbertigibbet-py") 

    def __init__(self): 
     super(UnsatisfiedExample, self).__init__() 

Voici mon shell Python expérience:

>>> import example 
You need to install flibbertigibbet-py 

Alternativement:

>>> from example import RedisExample 
You need to install flibbertigibbet-py 

je vraiment plutôt je n'ai pas eu cette erreur jusqu'à ce que j'ai essayé d'instancier un UnsatisfiedExample. Existe-t-il un moyen commun d'aborder ce problème? J'ai pensé à faire example un paquet avec chaque backend obtenir son propre module et en utilisant une fonction d'usine, mais je voulais m'assurer que je ne manquais pas quelque chose de mieux.

Merci.

+2

Après avoir un tel étonnant représentant votre question entière est dans le titre ...? –

+0

Il peut être utile de focaliser le titre et de fournir des détails dans le corps. Les détails aident, un peu de code presque-fonctionnant pour montrer ce que vous souhaitez arriver serait souvent utile. –

+0

Désolé les gars - J'ai un nouveau-né, donc la capacité de se concentrer est ici une minute, parti le lendemain. Je vais essayer de réviser. –

Répondre

5

Vous ne pouvez pas simplement mettre l'instruction import dans la méthode __init__ de chaque classe? Ensuite, il ne sera pas exécutée jusqu'à ce que vous essayez de faire une instance.

class UnsatisfiedExample(object): 
    def __init__(self): 
     try: 
      import flibbertigibbet 
     except ImportError: 
      raise RuntimeError("You need to install flibbertigibbet-py") 
     super(UnsatisfiedExample, self).__init__() 
+0

En outre, vous pouvez stocker la lib dans une variable d'instance, de sorte que vous puissiez y accéder plus tard dans votre classe: '' 'try: import flibbertigibbet; self.fg = flibbertigibbet''' – gaborous

4

import est juste une autre déclaration, comme for ou with. Mettez-le dans une instruction if, éventuellement derrière une classe d'abstraction.

+0

J'ai révisé la question pour fournir plus de détails. Pourriez-vous poster un exemple de l'idée de classe d'abstraction que vous avez mentionnée et comment cela répondrait à mon inquiétude (on l'espère plus claire maintenant)? –

+0

Ma réponse ne change pas. Effectuez l'importation lorsque vous en avez besoin. –

+0

Êtes-vous en train de suggérer que le code client fait simplement 'd'exemple import RedisExample' au lieu de' import example'? Parce que cela déclenche aussi 'ImportError'. –

Questions connexes