使用Python注入器模块命名的复制指南



我使用的注入器模块体现了DI框架的大部分Guice API。

我试图完成的是Guice对@Named绑定注释所做的工作。也就是说,使用injector.Module覆盖configure方法,并使用Binder绑定多个相同类型但名称不同的实例:

import pathlib
import injector
ConfigFile = pathlib.WindowsPath
UserFile = pathlib.WindowsPath
cfg_file = pathlib.Path.home() / 'settings.cfg'
usr_file = pathlib.Path.home() / 'user.inf'
class AppModule(injector.Module):
def configure(self, binder):
binder.bind(ConfigFile, to=cfg_file) # Guice uses annotatedWith here
binder.bind(UserFile, to=usr_file) # Guice uses annotatedWith here
class App:
@injector.inject
def __init__(self, cfg: ConfigFile, usr: UserFile):
self.config = cfg
self.user = usr
app = injector.Injector(AppModule).get(App)
print(app.config, app.user) # prints the contents of `usr_file` for both

我认为Binder.multibind我有一些可行性,但我的尝试一直没有成功。我能设计的唯一解决方案是pathlib.Path必须被子类化,并且这些子类显式绑定到它们的实例(可以在injector.Module中使用@provider和@singleton来管理(。

有没有另一种方法可以做到这一点,而不是解决问题?

可以从typeing_extensions(已经是注入器的依赖项或Python 3.9类型(中使用Annotated。在上面的例子中,只需替换

ConfigFile = pathlib.WindowsPath
UserFile = pathlib.WindowsPath

带有

ConfigFile = Annotated[pathlib.WindowsPath, 'config']
UserFile = Annotated[pathlib.WindowsPath, 'user']

它应该起作用。

打字是完全可能的。NewType,但它可能不会很好地与静态类型的跳棋配合使用。

以下是在python 3.6上测试的完整工作示例:

from injector import Injector, inject, Module, singleton, provider
from typing_extensions import Annotated
from typing import NewType, Callable
# You can use Greeting instead of Annotated[str, 'greeting'] as it's the same type
Greeting = Annotated[str, 'greeting']

class Greeter:
@inject
def __init__(self, greeting: Annotated[str, 'greeting']):
self.greeting = greeting
def greet(self):
print(self.greeting)

class MyModule(Module):
def configure(self, binder):
binder.bind(Greeting, to='Howdy', scope=singleton)
binder.bind(str, to='Hello', scope=singleton)

def main():
injector = Injector([MyModule()])
greeter = injector.get(Greeter)
greeter.greet()

if __name__ == '__main__':
main()

有一点问题,如果你不为Annotated[str, 'greeting']提供绑定,注入器将使用一个默认的构造函数,它会产生一些东西,但可能不是你所期望的。另一方面,它同样处理str——愉快地构造一个空字符串。

在安装了以下软件包的conda环境中进行测试(注射器使用pip安装(:

# Name                    Version
injector                  0.18.4 
libffi                    3.0.9  
pip                       18.1   
python                    3.6.8  
setuptools                40.8.0 
sqlite                    3.26.0 
typing-extensions         3.7.4.3
wheel                     0.33.1 
xz                        5.2.3  

最新更新