Python Dependency Injection Framework

PythonDependency Injection

Python Problem Overview


Is there a framework equivalent to Guice (http://code.google.com/p/google-guice) for Python?

Python Solutions


Solution 1 - Python

Spring Python is an offshoot of the Java-based Spring Framework and Spring Security, targeted for Python. This project currently contains the following features:

  • Inversion Of Control (dependency injection) - use either classic XML, or the python @Object decorator (similar to the Spring JavaConfig subproject) to wire things together. While the @Object format isn't identical to the Guice style (centralized wiring vs. wiring information in each class), it is a valuable way to wire your python app.

  • Aspect-oriented Programming - apply interceptors in a horizontal programming paradigm (instead of vertical OOP inheritance) for things like transactions, security, and caching.

  • DatabaseTemplate - Reading from the database requires a monotonous cycle of opening cursors, reading rows, and closing cursors, along with exception handlers. With this template class, all you need is the SQL query and row-handling function. Spring Python does the rest.

  • Database Transactions - Wrapping multiple database calls with transactions can make your code hard to read. This module provides multiple ways to define transactions without making things complicated.

  • Security - Plugin security interceptors to lock down access to your methods, utilizing both authentication and domain authorization.

  • Remoting - It is easy to convert your local application into a distributed one. If you have already built your client and server pieces using the IoC container, then going from local to distributed is just a configuration change.

  • Samples - to help demonstrate various features of Spring Python, some sample applications have been created:

    • PetClinic - Spring Framework's sample web app has been rebuilt from the ground up using python web containers including: CherryPy. Go check it out for an example of how to use this framework. (NOTE: Other python web frameworks will be added to this list in the future).
    • Spring Wiki - Wikis are powerful ways to store and manage content, so we created a simple one as a demo!
    • Spring Bot - Use Spring Python to build a tiny bot to manage the IRC channel of your open source project.

Solution 2 - Python

I like this simple and neat framework.

http://pypi.python.org/pypi/injector/

> Dependency injection as a formal pattern is less useful in Python than > in other languages, primarily due to its support for keyword > arguments, the ease with which objects can be mocked, and its dynamic > nature. > > That said, a framework for assisting in this process can remove a lot > of boiler-plate from larger applications. That's where Injector can > help. It automatically and transitively provides keyword arguments > with their values. As an added benefit, Injector encourages nicely > compartmentalized code through the use of Module s. > > While being inspired by Guice, it does not slavishly replicate its > API. Providing a Pythonic API trumps faithfulness.

Solution 3 - Python

I haven't used it, but the Spring Python framework is based on Spring and implements Inversion of Control.

There also appears to be a Guice in Python project: snake-guice

Solution 4 - Python

As an alternative to monkeypatching, I like DI. A nascent project such as http://code.google.com/p/snake-guice/ may fit the bill.

Or see the blog post Dependency Injection in Python by Dennis Kempin (Aug '08).

Solution 5 - Python

pinject (https://github.com/google/pinject) is a newer alternative. It seems to be maintained by Google and follows a similar pattern to Guice (https://code.google.com/p/google-guice/), it's Java counterpart.

Solution 6 - Python

Solution 7 - Python

If you just want to do dependency injection in Python, you don't need a framework. Have a look at Dependency Injection the Python Way. It's really quick and easy, and only c. 50 lines of code.

Solution 8 - Python

There is a somewhat Guicey python-inject project. It's quite active, and a LOT less code then Spring-python, but then again, I haven't found a reason to use it yet.

Solution 9 - Python

Will leave my 5 cents here :)

https://pypi.python.org/pypi/dependency_injector

"""Pythonic way for Dependency Injection."""

from dependency_injector import providers
from dependency_injector import injections


@providers.DelegatedCallable
def get_user_info(user_id):
    """Return user info."""
    raise NotImplementedError()


@providers.Factory
@injections.inject(get_user_info=get_user_info)
class AuthComponent(object):
    """Some authentication component."""

    def __init__(self, get_user_info):
        """Initializer."""
        self.get_user_info = get_user_info

    def authenticate_user(self, token):
        """Authenticate user by token."""
        user_info = self.get_user_info(user_id=token + '1')
        return user_info


print AuthComponent
print get_user_info


@providers.override(get_user_info)
@providers.DelegatedCallable
def get_user_info(user_id):
    """Return user info."""
    return {'user_id': user_id}


print AuthComponent().authenticate_user(token='abc')
# {'user_id': 'abc1'}

UPDATED

Some time passed and Dependency Injector is a bit different now. It's better to start from Dependency Injector GitHub page for getting actual examples - https://github.com/ets-labs/python-dependency-injector

Solution 10 - Python

After years using Python without any DI autowiring framework and Java with Spring I've come to realize that plain simple Python code often doesn't need a framework for dependency injection autowiring (autowiring is what Guice and Spring both do in Java), i.e., just doing something like this is enough:

def foo(dep = None):  # great for unit testing!
    ...

This is pure dependency injection (quite simple) but without magical frameworks for automatically injecting them for you.

Though as I dealt with bigger applications this approach wasn't cutting it anymore. So I've come up with injectable a micro-framework that wouldn't feel non-pythonic and yet would provide first class dependency injection autowiring.

Under the motto Dependency Injection for Humans™ this is what it looks like:

# some_service.py
class SomeService:
    @autowired
    def __init__(
        self,
        database: Autowired(Database),
        message_brokers: Autowired(List[Broker]),
    ):
        pending = database.retrieve_pending_messages()
        for broker in message_brokers:
            broker.send_pending(pending)
# database.py
@injectable
class Database:
    ...
# message_broker.py
class MessageBroker(ABC):
    def send_pending(messages):
        ...
# kafka_producer.py
@injectable
class KafkaProducer(MessageBroker):
    ...
# sqs_producer.py
@injectable
class SQSProducer(MessageBroker):
    ...

Solution 11 - Python

Here is a small example for a dependency injection container that does constructor injection based on the constructor argument names:

http://code.activestate.com/recipes/576609-non-invasive-dependency-injection/

Solution 12 - Python

I made a lib to do this https://github.com/ettoreleandrotognoli/python-cdi I hope that helps

It's available on pypi: https://pypi.python.org/pypi/pycdi

With it you can make injections with python2

import logging
from logging import Logger

from pycdi import Inject, Singleton, Producer
from pycdi.shortcuts import call


@Producer(str, _context='app_name')
def get_app_name():
    return 'PyCDI'


@Singleton(produce_type=Logger)
@Inject(app_name=str, _context='app_name')
def get_logger(app_name):
    return logging.getLogger(app_name)


@Inject(name=(str, 'app_name'), logger=Logger)
def main(name, logger):
    logger.info('I\'m starting...')
    print('Hello World!!!\nI\'m a example of %s' % name)
    logger.debug('I\'m finishing...')


call(main)

And using type hints from python3

import logging
from logging import Logger

from pycdi import Inject, Singleton, Producer
from pycdi.shortcuts import call


@Producer(_context='app_name')
def get_app_name() -> str:
    return 'PyCDI'


@Singleton()
@Inject(logger_name='app_name')
def get_logger(logger_name: str) -> Logger:
    return logging.getLogger(logger_name)


@Inject(name='app_name')
def main(name: str, logger: Logger):
    logger.info('I\'m starting...')
    print('Hello World!!!\nI\'m a example of %s' % name)
    logger.debug('I\'m finishing...')


call(main)

Solution 13 - Python

Enterprython is a small framework providing dependency-injection, building the object graph automatically based on type hints.

Solution 14 - Python

If you prefer a really tiny solution there's a little function, it is just a dependency setter.

https://github.com/liuggio/Ultra-Lightweight-Dependency-Injector-Python

Solution 15 - Python

There's dyject (http://dyject.com), a lightweight framework for both Python 2 and Python 3 that uses the built-in ConfigParser

Solution 16 - Python

If you want a guice like (the new new like they say), I recently made something close in Python 3 that best suited my simple needs for a side project.

All you need is an @inject on a method (_init_ included of course). The rest is done through annotations.

from py3njection import inject
from some_package import ClassToInject

class Demo:
    @inject
    def __init__(self, object_to_use: ClassToInject):
        self.dependency = object_to_use

demo = Demo()

https://pypi.python.org/pypi/py3njection

Solution 17 - Python

I recently released a neat (IMHO) micro library for DI in python:

https://github.com/suned/serum

Solution 18 - Python

I'm actively developing pinject for Python >= 3.6. It's quite easy to use:

class MyObject:
    my_service: MyService = INJECTED
    my_config: str = INJECTED

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMark RoddyView Question on Stackoverflow
Solution 1 - PythongregturnView Answer on Stackoverflow
Solution 2 - PythonMikhail HolovatyView Answer on Stackoverflow
Solution 3 - PythonMatthew TrevorView Answer on Stackoverflow
Solution 4 - Pythonuser35818View Answer on Stackoverflow
Solution 5 - PythonphssView Answer on Stackoverflow
Solution 6 - PythonBartosz RadaczyńskiView Answer on Stackoverflow
Solution 7 - PythonSkilldrickView Answer on Stackoverflow
Solution 8 - PythonY.H WongView Answer on Stackoverflow
Solution 9 - PythonRoman MogylatovView Answer on Stackoverflow
Solution 10 - PythonRodrigo Martins de OliveiraView Answer on Stackoverflow
Solution 11 - PythonchiborgView Answer on Stackoverflow
Solution 12 - PythonÉttore Leandro TognoliView Answer on Stackoverflow
Solution 13 - PythonTobias HermannView Answer on Stackoverflow
Solution 14 - PythonBillMartusView Answer on Stackoverflow
Solution 15 - PythondjsumdogView Answer on Stackoverflow
Solution 16 - PythonAigrefinView Answer on Stackoverflow
Solution 17 - PythonSune Andreas Dybro DebelView Answer on Stackoverflow
Solution 18 - PythonDavidView Answer on Stackoverflow