I have a fairly simple set of functionality for which I have multiple implementations, e.g., a datastore that could be backed by Redis, MongoDB, or PostgreSQL. How should I structure/write my code so that code that wants to use one of these implementations only needs the dependencies for that implementation, e.g., they don't need to have psycopg2
installed if they are using the Redis backend.
Here's an example. Assume the following module, 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__()
Here's my Python shell experience:
>>> import example
You need to install flibbertigibbet-py
Alternately:
>>> from example import RedisExample
You need to install flibbertigibbet-py
I'd really rather I didn't get that error until I tried to instantiate an 开发者_如何学CUnsatisfiedExample
. Is there any sort of common way to approach this problem? I've thought about making example
a package with each backend getting its own module and using a factory function, but I wanted to make sure I wasn't missing something better.
Thanks.
Can't you simply put the import
statement in the __init__
method of each class? Then it won't be run until you try to make an instance:
class UnsatisfiedExample(object):
def __init__(self):
try:
import flibbertigibbet
except ImportError:
raise RuntimeError("You need to install flibbertigibbet-py")
super(UnsatisfiedExample, self).__init__()
import
is just another statement, like for
or with
. Put it in an if
statement, possibly behind an abstraction class.
精彩评论