Python Dependency Injection

 

Python: importing settings or dependency injection

Two common approaches to configuring a python application are importing settings and dependency injection.

Importing settings involves creating a settings module or file that contains all the values and configurations needed for your application to run. These settings can then be imported into other modules and used directly. The advantage of this approach is that it is simple and easy to understand, and can work for small projects. The disadvantage is that it increases coupling to the settings module and to the way that those settings are collected. It also makes it harder to unit test a module or class without having to resort to mocking the settings module in some way.

Dependency injection involves passing dependencies (such as settings) into a class as parameters, typically using a class method that sets some class variables.

The advantage of this is that the class needs no knowledge of the settings module or how those settings are loaded. It also makes testing easier because tests can either rely on the classes default settings or inject their own test settings. The class can also be re-used more easily.

Compare these two examples:

Importing Settings

Common in older Python code. Settings imported and used everywhere.

settings.py

# Some settings as class variables.. maybe use pydantic BaseSettings
class Settings():
    some_setting = "some_value"

some_class.py

from settings import Settings

class SomeClass():
    SOME_SETTING = Settings.some_setting

    def __init__(self):
        print(f"SOME_SETTING = {self.SOME_SETTING}")

Basic Dependency Injection

Better: import settings and configure classes in one place.

settings.py

# Some settings as class variables.. maybe use pydantic BaseSettings
class Settings():
    some_setting = "some_value"

    # Inject the settings into the SomeClass class
    from some_class import SomeClass
    SomeClass.configure(some_setting=Settings.some_setting

some_class.py

class SomeClass():
    SOME_SETTING = "default"

    @classmethod
    def configure(some_setting):
        SOME_SETTING = some_setting

    def __init__(self):
        print(f"SOME_SETTING = {self.SOME_SETTING}")
 

Other Dependency Injection methods exist

 

https://python-dependency-injector.ets-labs.org/ 

I quite like this one, because it's independent of other frameworks.

https://fastapi.tiangolo.com/tutorial/dependencies/

If you're using FastAPI, it has its own DI framework. 

Comments

Popular posts from this blog

Handling and Tyre wear patterns

Getting FlashFloppy onto the Gotek SFRC922D