DI in python
code on githubHandling DI in python
Let's write a simple wiring of two services, A and B. first we can capture the behaviour of the service via two abstract base classes (ABCs), `ServiceA` and `ServiceB`, and then create multiple concrete implementations for each of these services.
from abc import ABC, abstractmethod
class ServiceA(ABC):
@abstractmethod
def execute(self):
pass
class ServiceAImpl1(ServiceA):
def execute(self):
return "Executing Service A Impl 1"
class ServiceAImpl2(ServiceA):
def execute(self):
return "Executing Service A Impl 2"
class ServiceB(ABC):
@abstractmethod
def run(self):
pass
class ServiceBImpl1(ServiceB):
def run(self):
return "Running Service B Impl 1"
class ServiceBImpl2(ServiceB):
def run(self):
return "Running Service B Impl 2"
Now, we can define a configuration file which will specify which implementation to be used for ServiceA and ServiceB
[SERVICES]
ServiceA = ServiceAImpl1
ServiceB = ServiceBImpl2
This file specifies ServiceA, should use ServiceAImpl1 and for ServiceB, it should use ServiceBImpl2.
Then, to use the configuration, we can use python's configparser to get the correct class implementations:
# assumes that the services and the main loading script are in the same module.
import configparser
config = configparser.ConfigParser()
config.read('config.ini')
def get_service_implementation(service_name, default=None):
try:
class_name = config['SERVICES'].get(service_name, default)
module = __import__(__name__)
class_ = getattr(module, class_name)
return class_()
except (AttributeError, ImportError):
return None # do something more appropriate...
service_a_instance = get_service_implementation('ServiceA')
service_b_instance = get_service_implementation('ServiceB')
print(service_a_instance.execute())
print(service_b_instance.run())
this would print:
Executing Service A Impl 1
Running Service B Impl 2