为什么文档使用 lru_cache 装饰函数来获取设置,而不是直接从模块导入初始化的设置对象

Why does documentation use lru_cache decorated function to get settings, instead of importing an initialized settings object from the module directly

FastAPI 文档建议使用 lru_cache 装饰函数来检索配置文件。避免 I/O 获取 env 文件是有意义的。

config.py
from pydantic import BaseSettings


class Settings(BaseSettings):
    app_name: str = "Awesome API"
    admin_email: str
    items_per_user: int = 50

    class Config:
        env_file = ".env"

然后在其他模块中,文档实现了一个获取设置的函数

#module_omega.py
from . import config

@lru_cache()
def get_settings():
    return config.Settings()

settings = get_settings()
print(settings.ENV_VAR_ONE)

我想知道这种方法是否是更好的做法或有利于仅在配置模块中初始化一个设置对象,然后像下面那样导入它。

#config.py
from pydantic import BaseSettings


class Settings(BaseSettings):
    app_name: str = "Awesome API"
    admin_email: str
    items_per_user: int = 50

    class Config:
        env_file = ".env"

settings = Settings()

#module_omega.py

from .config import settings

print(settings.ENV_VAR_ONE)

我知道你问已经有一段时间了,虽然我同意评论者的观点,即它们在功能上是等价的,但我可以指出另一个重要的区别,我认为它激发了 @lru_cache 的使用。

@lru_cache 方法可以帮助限制导入模块时执行 的代码量。

settings = Settings()

按照您的建议,通过这样做,您将导出 settings 实例 。这意味着您正在传递执行任何需要 运行 在导入模块时立即创建 settings 的代码。

虽然模块导出 are cached 类似于 @lru_cache 的方式,但您对延迟加载设置没有太多控制,因为在 python 中我们通常放置我们在文件顶部导入。

如果您有更昂贵的设置,例如查看文件系统或访问网络,@lru_cache 技术特别有用。这样你就可以推迟加载你的设置,直到你真的需要它们。

from . import get_settings

def do_something_with_deferred_settings():
    print(get_settings().my_setting)

if __name__ == "__main__":
    do_something_with_deferred_settings()

其他需要调查的事项:

  • @cache 在 python 3.9 而不是 @lru_cache
  • Module __getattr__ 不在此处添加任何 IMO,但在使用动态和导入系统时它会很有用。