Injector

Injector is a Python IOC for Pythonic class dependency injection. It allows you to define dependencies on classes as constructor arguments and then use the Injector class to create the object without having to reference all the dependency arguments directly. At its heart Injector is just a dictionary that returns an object when a type is specified.

To install injector use the injector handle with pip.

$ pip3 install injector

Bindings

A binding allows you to define how “typed” dependency argument is constructed and returned to the object that uses it. This is essentially just a way of generating a dictionary with the keys as a types that you want to use the values as the instantiaton of those types. The example below shows a user function that has a DatabaseConnection as its dependency which is indicated by the type hint on db. To tell the Injector what to pass to the function when it is called we set up a configure function that takes a binder as its argument. We then use the bind method on the binder to specify a type and to what that type should be converted when the function is called and requires its dependency. By default Injector creates an instance of whatever type you set as it goingto, so in the example below the DatabaseConnection is automatically created.

def user(db: DatabaseConnection):
  # use database connection

def configure(binder):
  binder.bind(DatabaseConnection, to=DatabaseConnection)

Using also use a binding you can define nested dependencies instead of using the @inject syntax.


To define a dependency injected constructor use the @inject decorator on a class constructor. The dependencies must also be typed with hints so Injector knows which classes to inject. In the example below the Container class’ constructor is marked with the @inject decorator and then the type hinter Dependency class is indicated as its dependency.

# class_examples.py
from injector import inject

class Dependency:
  __init__(self):
    self.data = 6744

class Container:
  @inject
  __init__(self, dependency: Dependency):
    self.dependency = dependency

You can instantiate a dependency injected class by creating a new instance of Injector and using the get method with the class you want to instantiate as its argument. You only need to import the highest level class to the place where it is instantiated with all dependencies to be found.

from injector import Injector

# make a new injector instance
injector = Injector()
# create a new container instance with dependencies automatically injected
container = injector.get(Container)
container.dependency.data # => 6744

You can nest injected classes by placing the @inject decorator on injected sub classes. You still only need to create the outer class for all nested dependencies to be found.

Flask-Injector

You can combine flask route injection with general @inject syntax for managing class dependencies.