Python Dependency Injection Framework

后端 未结 18 2166
你的背包
你的背包 2020-12-12 14:10

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

相关标签:
18条回答
  • 2020-12-12 14:12

    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.

    0 讨论(0)
  • 2020-12-12 14:13

    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):
        ...
    
    0 讨论(0)
  • 2020-12-12 14:15

    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.
    0 讨论(0)
  • 2020-12-12 14:15

    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
    
    0 讨论(0)
  • 2020-12-12 14:17

    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)
    
    0 讨论(0)
  • 2020-12-12 14:18

    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

    0 讨论(0)
提交回复
热议问题