Reputation: 27986
Is there a framework equivalent to Guice (http://code.google.com/p/google-guice) for Python?
Upvotes: 53
Views: 44282
Reputation: 1912
Here's a good comparison (19 September 2020): Comparison of Dependency Injection Libraries in Python, and my favorite one
His winners are:
proofit404/dependencies (Injector) "simple, but provided all the necessary features. If you need something that’s not provided then just think about the design in your application, cause the flow might be somewhere there. Beautiful configuration. Perfect match for agile projects"
ets-labs/python-dependency-injector "very expanded library, with constant support, the problem is it’s boilerplate, if that does not bother you, then it’s a great choice"
Upvotes: 1
Reputation: 3152
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
Upvotes: 0
Reputation: 1582
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):
...
Upvotes: 4
Reputation: 10986
Enterprython is a small framework providing dependency-injection, building the object graph automatically based on type hints.
Upvotes: 1
Reputation: 503
I recently released a neat (IMHO) micro library for DI in python:
https://github.com/suned/serum
Upvotes: 0
Reputation: 170
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)
Upvotes: 1
Reputation: 566
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
Upvotes: 3
Reputation: 125
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
Upvotes: 0
Reputation: 7244
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.
Upvotes: 3
Reputation: 1022
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.
Upvotes: 9
Reputation: 2714
There's dyject (http://dyject.com), a lightweight framework for both Python 2 and Python 3 that uses the built-in ConfigParser
Upvotes: 0
Reputation: 311
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.
Upvotes: 21
Reputation: 111
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).
Upvotes: 11
Reputation: 28154
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/
Upvotes: 1
Reputation: 1
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
Upvotes: 0
Reputation: 70889
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.
Upvotes: 3
Reputation: 2693
Spring Python is an offshoot of the Java-based Spring Framework and Spring Security, targeted for Python. This project currently contains the following features:
Upvotes: 25