Python Dependency Injection Framework
PythonDependency InjectionPython 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
Besides that:
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()
Solution 17 - Python
I recently released a neat (IMHO) micro library for DI in python:
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