受guice启发的注入器python依赖注入框架
injector的Python项目详细描述
简介
依赖注入作为一种形式模式在python中不如 在其他语言中,主要是因为它支持关键字参数, 对象被模仿的容易程度及其动态特性。
也就是说,一个协助这个过程的框架可以消除很多 更大用途的锅炉板。这是注射器可以帮助的地方。 它自动且可传递地提供关键字参数 价值观。作为一个额外的好处,注入器可以很好地鼓励 通过使用Modules来划分代码。
虽然受到guice的启发,但它并没有盲目地复制自己的api。 提供一个Python般的api胜过忠诚。
如何得到注射器?
Github(代码库,问题): https://github.com/alecthomas/injector
PYPI(可安装、稳定的发行版): https://pypi.python.org/pypi/injector。您可以使用pip安装它:
pip install injector
更改日志:http://injector.readthedocs.io/en/latest/changelog.html
injector与cpython 3.5+和pypy3一起实现python3.5+。
一个简单的例子
>>>frominjectorimportInjector,inject>>>classInner:...def__init__(self):...self.forty_two=42...>>>classOuter:...@inject...def__init__(self,inner:Inner):...self.inner=inner...>>>injector=Injector()>>>outer=injector.get(Outer)>>>outer.inner.forty_two42
如果您愿意,也可以使用dataclasses:
fromdataclassesimportdataclassfrominjectorimportInjector,injectclassInner:def__init__(self):self.forty_two=42@inject@dataclassclassOuter:inner:Innerinjector=Injector()outer=injector.get(Outer)print(outer.inner.forty_two)# Prints 42
完整示例
下面是一个完整的示例,让您了解喷油器的工作原理:
>>>frominjectorimportModule,Key,provider,Injector,inject,singleton
我们将使用内存中的sqlite数据库作为示例:
>>>importsqlite3
并构造一个虚构的RequestHandler类,该类使用sqlite 连接:
>>>classRequestHandler:...@inject...def__init__(self,db:sqlite3.Connection):...self._db=db......defget(self):...cursor=self._db.cursor()...cursor.execute('SELECT key, value FROM data ORDER by key')...returncursor.fetchall()
接下来,为了示例起见,我们将创建一个配置类型:
>>>classConfiguration:...def__init__(self,connection_string):...self.connection_string=connection_string
接下来,我们使用模块将配置绑定到喷油器:
>>>defconfigure_for_testing(binder):...configuration=Configuration(':memory:')...binder.bind(Configuration,to=configuration,scope=singleton)
接下来我们创建一个初始化数据库的模块。这取决于 上述模块提供的用于创建新数据库的配置 连接,然后用一些虚拟数据填充它,并提供 Connection对象:
>>>classDatabaseModule(Module):...@singleton...@provider...defprovide_sqlite_connection(self,configuration:Configuration)->sqlite3.Connection:...conn=sqlite3.connect(configuration.connection_string)...cursor=conn.cursor()...cursor.execute('CREATE TABLE IF NOT EXISTS data (key PRIMARY KEY, value)')...cursor.execute('INSERT OR REPLACE INTO data VALUES ("hello", "world")')...returnconn
(注意我们如何将配置与数据库分离 初始化代码。)
最后,我们初始化一个Injector,并使用它来实例化 RequestHandler实例。第一个可传递的构造 sqlite3.Connection对象,以及 依次需要,然后实例化我们的RequestHandler:
>>>injector=Injector([configure_for_testing,DatabaseModule()])>>>handler=injector.get(RequestHandler)>>>tuple(map(str,handler.get()[0]))# py3/py2 compatibility hack('hello','world')
我们还可以验证我们的Configuration和SQLite连接 喷油器内是否确实存在单重态:
>>>injector.get(Configuration)isinjector.get(Configuration)True>>>injector.get(sqlite3.Connection)isinjector.get(sqlite3.Connection)True
你可能会想:“这是一项庞大的工作 只是给我一个数据库连接“,你是对的;依赖 对于较小的项目,注入通常没有那么有用。它来了 在大型项目中投入自己的前期工作 有两种方式:
- 迫使脱钩。在我们的例子中,这通过解耦来说明 我们的配置和数据库配置。
- 配置类型后,可以在任何位置注入 额外的努力。只要@inject,它就会出现。我们不是真的 在这里举例说明,但是你可以想象添加任意数字 所有子类都将自动 提供数据库连接。
脚注
这个框架类似于snake guice,但目的是简化。
版权所有2010-2013归Alec Thomas所有,根据BSD许可证