Is there a framework equivalent to Guice (http://code.google.com/p/google-guice) for 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.
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):
...
Spring Python is an offshoot of the Java-based Spring Framework and Spring Security, targeted for Python. This project currently contains the following features:
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
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)
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