是否有与Python的 Guice ( http://code.google.com/p/google-guice ) 等效的框架?
18 回答
Spring Python是基于 Java 的 Spring Framework 和 Spring Security 的一个分支,面向 Python。该项目目前包含以下功能:
- 控制反转(依赖注入) - 使用经典 XML 或 python @Object 装饰器(类似于 Spring JavaConfig 子项目)将事物连接在一起。虽然@Object 格式与 Guice 样式不同(集中连接与每个类中的连接信息),但它是连接 Python 应用程序的一种有价值的方式。
- 面向方面的编程- 在水平编程范式(而不是垂直 OOP 继承)中应用拦截器,用于事务、安全和缓存等事务。
- DatabaseTemplate - 从数据库读取需要打开游标、读取行和关闭游标的单调循环,以及异常处理程序。使用这个模板类,您只需要 SQL 查询和行处理功能。Spring Python 完成了剩下的工作。
- 数据库事务 - 使用事务包装多个数据库调用会使您的代码难以阅读。该模块提供了多种方法来定义事务,而不会使事情变得复杂。
- 安全性 - 使用身份验证和域授权来锁定对您的方法的访问的插件安全拦截器。
- 远程处理 - 将本地应用程序转换为分布式应用程序很容易。如果您已经使用 IoC 容器构建了客户端和服务器部分,那么从本地到分布式只是一个配置更改。
- 示例 - 为了帮助演示 Spring Python 的各种功能,创建了一些示例应用程序:
- PetClinic - Spring Framework 的示例 Web 应用程序已使用 python Web 容器从头开始重建,包括:CherryPy . 去看看如何使用这个框架的例子。(注意:其他 python web 框架将来会被添加到这个列表中)。
- Spring Wiki - Wiki 是存储和管理内容的强大方式,因此我们创建了一个简单的演示版!
- Spring Bot - 使用 Spring Python 构建一个小型机器人来管理开源项目的 IRC 通道。
我喜欢这个简单而整洁的框架。
http://pypi.python.org/pypi/injector/
依赖注入作为一种正式模式在 Python 中不如在其他语言中有用,这主要是因为它支持关键字参数、可以轻松地模拟对象以及它的动态特性。
也就是说,用于协助此过程的框架可以从大型应用程序中删除大量样板。这就是 Injector 可以提供帮助的地方。它自动和传递地提供关键字参数及其值。作为一个额外的好处,Injector 鼓励通过使用 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 中进行依赖注入,则不需要框架。看看Python 方式的依赖注入。它真的又快又容易,而且只有 c. 50行代码。
有一个有点 Guicey 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 现在有点不同了。最好从 Dependency Injector GitHub 页面开始获取实际示例 - https://github.com/ets-labs/python-dependency-injector
下面是一个依赖注入容器的小例子,它根据构造函数参数名称进行构造函数注入:
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是一个提供依赖注入的小型框架,根据类型提示自动构建对象图。
如果您更喜欢一个非常小的解决方案,那么它有一个小功能,它只是一个依赖设置器。
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 中为 DI 发布了一个简洁的(恕我直言)微库:
我正在积极为 Python >=开发pinject3.6
。它很容易使用:
class MyObject:
my_service: MyService = INJECTED
my_config: str = INJECTED