DI (Dependency Injection) in Python

DI with Python

There seems to be no demand, but I happened to find out how to DI with Python, so ...

Several options

Inject seems to have stopped developing in 2015. di-py doesn't seem to be very well documented. I avoided siringa because it was a bit of a metamorphic way to inject type hints.

I tried Injector by elimination method.

Injector features

As explained in the documentation, it's a Google Guice -like framework. The explanation of Google Guice was easy to understand in this article. Google Guice usage memo

Terms such as Inject, Module, and Provider are almost the same as Google Guice, so it may be easier to understand Guice first. (Although there are still type hints, doing DI in a scripting language was hard to understand)

Implementation example

DI the instance

todo_usecase.py



@singleton
class TodoUseCase:

    def register(self, todo: Todo) - > None:
        print("call todo_usecase.register")

todo_controller.py



@singleton
class TodoController:

    @inject
    def __init__(self, todo_usecase: TodoUseCase) -> None:
        self.todo_usecase = todo_usecase

    def create_todo(self, todo: Todo) -> None:
        self.todo_usecase.register(todo)

if __name__=='__main__':
    injector = Injector()
    todo_controller: TodoController = injector.get(TodoController)

    todo: Todo = Todo()

    todo_controller.create_todo(todo)

If you want to DI a normal instance, just @Inject will do the DI for you. By default, it seems to be a singleton by giving @singleton instead of a singleton. (Guice is also not a singleton by default)

DI an instance of the implementation class

todo_repository.py



class TodoRepository:

    @abstractmethod
    def register(self, todo: Todo) -> None:
        raise NotImplementedError

todo_datasource.py



class TodoDataSource(TodoRepository):

    def register(self, todo: Todo) -> None:
        print("call todo_datasource.register")

todo_usecase.py



@singleton
class TodoUseCase:

        @inject
    def __init__(self, todo_repository: TodoRepository) -> None:
        self.todo_repository = todo_repository

    def register(self, todo: Todo) -> None:
        self.todo_repository.register(todo=todo)

class TodoDIModule(Module):
    def configure(self, binder):
        binder.bind(TodoRepository, to=TodoDataSource, scope=singleton)

if __name__=='__main__':
    injector = Injector([TodoDIModule()])
    todo_use_case: TodoUseCase = injector.get(TodoUseCase)

    todo: Todo = Todo()

    todo_use_case.register(todo)

The point is to set DI in the implementation class of Module. It seems that the method of making it a singleton can also be done by specifying the scope in Module.

that's all.

Recommended Posts

DI (Dependency Injection) in Python
dll injection in python
[Python] DI (Dependency Injection) container Which one should I use?
Quadtree in Python --2
Python in optimization
CURL in python
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Unittest in python
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
Plink in Python
Constant in python
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
StepAIC in Python
N-gram in python
LINE-Bot [0] in Python
Disassemble in Python
Reflection in Python
Constant in python
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Quad-tree in Python
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
LiNGAM in Python
Flatten in python
Meaning of using DI framework in Python
flatten in python
[Environment construction] Dependency analysis using CaboCha in Python 2.7
Sorted list in Python
Clustering text in Python
Daily AtCoder # 2 in Python
Implement Enigma in python
Daily AtCoder # 6 in Python
Daily AtCoder # 18 in Python
Edit fonts in Python
Singleton pattern in Python
File operations in Python
Read DXF in python
Daily AtCoder # 53 in Python
Key input in Python
Use config.ini in Python
Daily AtCoder # 33 in Python
Solve ABC168D in Python
Logistic distribution in Python
LU decomposition in Python