【发布时间】:2010-09-14 10:46:21
【问题描述】:
是否有与 Python 的 Guice (http://code.google.com/p/google-guice) 等效的框架?
【问题讨论】:
标签: python dependency-injection
是否有与 Python 的 Guice (http://code.google.com/p/google-guice) 等效的框架?
【问题讨论】:
标签: python dependency-injection
Spring Python 是基于 Java 的 Spring Framework 和 Spring Security 的一个分支,面向 Python。该项目目前包含以下功能:
【讨论】:
我喜欢这个简单整洁的框架。
http://pypi.python.org/pypi/injector/
依赖注入作为一种正式模式在 Python 中的用处不如 在其他语言中,主要是因为它支持关键字 论点,对象可以被模拟的难易程度,以及它的动态性 自然。
也就是说,协助这个过程的框架可以消除很多 来自较大应用的样板。这就是注射器可以的地方 帮助。它自动和传递地提供关键字参数 与他们的价值观。作为一个额外的好处,注射器很好地鼓励 通过使用 Module 来划分代码。
虽然受到 Guice 的启发,但它并没有盲目地复制其 API。提供 Pythonic API 胜过忠诚度。
【讨论】:
我没用过,不过Spring Python框架是基于Spring实现的Inversion of Control。
Python 项目中似乎也有一个 Guice:snake-guice
【讨论】:
作为猴子补丁的替代方案,我喜欢 DI。 http://code.google.com/p/snake-guice/ 等新生项目可能符合要求。
或查看 Dennis Kempin 的博文 Dependency Injection in Python(2008 年 8 月)。
【讨论】:
pinject (https://github.com/google/pinject) 是一种较新的替代方案。它似乎由 Google 维护,并遵循与 Guice (https://code.google.com/p/google-guice/) 类似的模式,它是 Java 对应物。
【讨论】:
【讨论】:
如果您只想在 Python 中进行依赖注入,则不需要框架。看看Dependency Injection the Python Way。它真的又快又容易,而且只有 c. 50 行代码。
【讨论】:
有一个有点奇怪的python-inject 项目。它非常活跃,而且代码比 Spring-python 少很多,但话说回来,我还没有找到使用它的理由。
【讨论】:
将我的 5 美分留在这里 :)
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'}
更新
一段时间过去了,依赖注入器现在有点不同了。最好从 Dependency Injector GitHub 页面开始获取实际示例 - https://github.com/ets-labs/python-dependency-injector
【讨论】:
多年使用没有任何 DI 自动装配框架的 Python 和带有 Spring 的 Java,我开始意识到简单的 Python 代码通常不需要依赖注入自动装配的框架(自动装配是 Guice 和 Spring 在 Java 中所做的) ,也就是说,只要做这样的事情就足够了:
def foo(dep = None): # great for unit testing!
...
这是纯粹的依赖注入(非常简单),但没有自动为您注入它们的神奇框架。
尽管当我处理更大的应用程序时,这种方法不再适用。所以我想出了injectable 一个微框架,它不会让人感觉非pythonic,但会提供一流的依赖注入自动装配。
在座右铭 Dependency Injection for Humans™ 下,它看起来是这样的:
# 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):
...
【讨论】:
这是一个依赖注入容器的小例子,它根据构造函数参数名称进行构造函数注入:
http://code.activestate.com/recipes/576609-non-invasive-dependency-injection/
【讨论】:
我做了一个库来做这个 https://github.com/ettoreleandrotognoli/python-cdi 希望对你有帮助
它在 pypi 上可用:https://pypi.python.org/pypi/pycdi
有了它你可以用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)
并使用来自 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)
【讨论】:
Enterprython是一个提供依赖注入的小框架,基于type hints自动构建对象图。
【讨论】:
如果你更喜欢一个非常小的解决方案,那么它就是一个小函数,它只是一个依赖设置器。
https://github.com/liuggio/Ultra-Lightweight-Dependency-Injector-Python
【讨论】:
有 dyject (http://dyject.com),这是一个适用于 Python 2 和 Python 3 的轻量级框架,它使用内置的 ConfigParser
【讨论】:
如果你想要一个类似(他们说的新的新的)的 guice,我最近在 Python 3 中做了一些最适合我对副项目的简单需求的东西。
您所需要的只是方法上的 @inject(当然包括 __init__)。 其余的通过注解来完成。
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()
【讨论】:
我最近在 python 中发布了一个简洁的(恕我直言)微库:
【讨论】:
我正在积极为 Python >= 3.6 开发 pinject。它很容易使用:
class MyObject:
my_service: MyService = INJECTED
my_config: str = INJECTED
【讨论】: