背景

  • 在许多情况下,应用程序可能需要一些外部设置或配置,例如密钥、数据库凭据、电子邮件服务凭据等。
  • 大多数这些设置都是可变的(可以更改),例如数据库 URL,很多可能是敏感数据,比如密码
  • 出于这个原因,通常在应用程序读取的环境变量中提供它们

Pydantic Settings

  • Pydantic 提供了一个很好的实用程序来处理环境变量的设置
  • 从 Pydantic 导入 BaseSettings 并创建一个子类,非常类似于 Pydantic 的 BaseModel
  • 与 Pydantic Model 一样,可以使用类型注释和默认值声明类属性
  • 可以使用和 Pydantic Model 的所有相同验证功能和工具,例如不同的数据类型和使用 Field()
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠萝测试笔记
# blog: https://www.cnblogs.com/poloyy/
# time: 2021/10/9 7:25 下午
# file: 52_settings_env.py
"""
import os import uvicorn
from fastapi import FastAPI
from pydantic import BaseSettings class Settings(BaseSettings):
app_name: str = "Awesome API"
admin_email: str
items_per_user: int = 50 settings = Settings()
app = FastAPI() @app.get("/info")
async def info():
return {
"app_name": settings.app_name,
"admin_email": settings.admin_email,
"items_per_user": settings.items_per_user,
}
  • 然后,当创建 Settings 该类的实例时,Pydantic 将以不区分大小写的方式读取环境变量
  • 因此,仍会为属性 app_name 读取为大写变量 APP_NAME
  • 接下来它将转换和验证数据
  • 因此,当使用该 settings 对象时,将拥有声明的类型的数据(例如 items_per_user 是 int)

运行 uvicorn 服务器

要为单个命令设置多个环境变量,只需用空格分隔它们,并将它们全部放在命令之前

ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" uvicorn main:app

访问 /info 接口

Settings 跨模块调用

config.py

from pydantic import BaseSettings

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

main.py

from fastapi import FastAPI
from .config import settings app = FastAPI() @app.get("/info")
async def info():
return {
"app_name": settings.app_name,
"admin_email": settings.admin_email,
"items_per_user": settings.items_per_user,
}

Settings 在依赖项中

前言

  • 在某些情况下,提供依赖项的 Settings 会有用,而不是让全局对象拥有可随处使用的 Settings
  • 在测试期间会有用,因为使用自定义 Settings 覆盖依赖项非常容易

config.py

from pydantic import BaseSettings

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

这里不创建默认实例 settings = Settings()

main.py

from fastapi import FastAPI, Depends
from functools import lru_cache
from .config import Settings app = FastAPI() @lru_cache
def get_settings():
return Settings @app.get("/info")
async def info(settings: Settings = Depends(get_settings)):
return {
"app_name": settings.app_name,
"admin_email": settings.admin_email,
"items_per_user": settings.items_per_user,
}

测试上述接口

from fastapi.testclient import TestClient
from .config import Settings
from .main import app, get_settings client = TestClient(app) # 依赖覆盖,为 Settings 对象设置一个新的 admin_email 值
def get_settings_override():
return Settings(admin_email="testing_admin@example.com") app.dependency_overrides[get_settings] = get_settings_override def test_app():
response = client.get("/info")
data = response.json()
assert data == {
"app_name": "Awesome API",
"admin_email": "testing_admin@example.com",
"items_per_user": 50,
}

命令行执行

> pytest 53_settings_test.py
============================================================================================================ test session starts ============================================================================================================
platform darwin -- Python 3.9.5, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /Users/polo/Downloads/FastAPI_project
plugins: anyio-3.3.2
collected 1 item 53_settings_test.py . [100%] ============================================================================================================= 1 passed in 0.30s =============================================================================================================

使用 .env 文件

背景

如果有会经常变化的设置项,也许在不同的环境中,将它们放在一个文件中,然后从文件中读取它们,就好像它们是环境变量一样

这些环境变量通常放在一个文件 .env 中,该文件称为“dotenv”

tips

  • 以点 (.) 开头的文件是类 Unix 系统(如 Linux 和 macOS)中的隐藏文件
  • 但是 dotenv 文件实际上不必具有那个确切的文件名
  • Pydantic 支持使用外部库读取这类型的文件

安装第三方库

pip install python-doten

.env 文件

ADMIN_EMAIL="xiaopolo@example.com"
APP_NAME="小菠萝"

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 文件
env_file = ".env"

lru_cache

背景

继上面的栗子,读取 .env 文件可能是一件代价高昂(缓慢)的操作

从性能角度出发,肯定希望只读取一次,后续每个请求可以重复使用同一个 Settings 对象,这样就只会读取一次 .env 文件

def get_settings():
return Settings()

上述代码,如果作为请求的依赖项,那么每次请求进来,都会创建一个 Settings 对象,然后读取一次 .env 文件,这不是我们希望的

@lru_cache

如果加上了 @lru_cache 那么 get_settings 只会在第一次调用的时候执行一次,然后 Settings 对象也只会创建一次,.env 文件也只会读取一次

from functools import lru_cache
from fastapi import Depends, FastAPI
from . import config app = FastAPI() @lru_cache()
def get_settings():
return config.Settings() @app.get("/info")
async def info(settings: config.Settings = Depends(get_settings)):
return {
"app_name": settings.app_name,
"admin_email": settings.admin_email,
"items_per_user": settings.items_per_user,
}

对于后续请求的依赖项中的 get_settings() 的任何后续调用,它不会执行 get_settings() 的内部代码并创建新的 Settings 对象,而是返回与第一次调用时返回的相同对象

lru_cache 技术细节

  • @lru_cache() 修改它修饰的函数返回与第一次返回相同的值,而不是再次执行函数内部代码
  • 因此,它下面的函数将针对每个参数组合执行一次
  • 然后,每当使用完全相同的参数组合调用函数时,每个参数组合返回相同的值将一次又一次地使用
  • 在请求依赖项 get_settings() 的情况下,该函数没有参数,所以它总是返回相同的值
  • 这样,它的行为就好像它只是一个全局变量
  • 但是因为它使用了一个依赖函数,所以可以很容易地覆盖它进行测试
  • @lru_cache() 是 functools 的一部分,它是 Python 标准库的一部分
  • 使用 @lru_cache() 可以避免为每个请求一次又一次地读取 .env 文件,同时可以在测试期间覆盖它的值

有参数的函数的栗子

@lru_cache()
def say_hi(name: str, salutation: str = "Ms."):
print(123)
return f"Hello {salutation} {name}" print(say_hi(name="Camila"))
print(say_hi(name="Camila")) print(say_hi(name="Rick", salutation="Mr."))
print(say_hi(name="Rick", salutation="Mr.")) print(say_hi(name="Camila"))
print(say_hi(name="Rick", salutation="Mr."))

运行结果

123
Hello Ms. Camila
Hello Ms. Camila 123
Hello Mr. Rick
Hello Mr. Rick Hello Ms. Camila
Hello Mr. Rick

使用完全相同的参数调用函数时,直接返回结果而不会执行厘米的代码

原理图

FastAPI(64)- Settings and Environment Variables 配置项和环境变量的更多相关文章

  1. CMake语法—环境变量(Environment Variable)

    目录 CMake语法-环境变量(Environment Variable) 1 定义环境变量 2 应用环境变量 2.1 代码结构 2.2 示例代码 2.3 运行结果 3 小结 CMake语法-环境变量 ...

  2. Debian Environment Variables

    原文:EnvironmentVariables General Environment variables are named strings available to all application ...

  3. Environment Variables

    https://msdn.microsoft.com/en-us/library/windows/desktop/ms682653(v=vs.85).aspx Every process has an ...

  4. Visual Studio Set Project Environment Variables

    Visual Studio Set Project Environment Variables eryar@163.com In Visual Studio you can specify chang ...

  5. CVE: 2014-6271、CVE: 2014-7169 Bash Specially-crafted Environment Variables Code Injection Vulnerability Analysis

    目录 . 漏洞的起因 . 漏洞原理分析 . 漏洞的影响范围 . 漏洞的利用场景 . 漏洞的POC.测试方法 . 漏洞的修复Patch情况 . 如何避免此类漏洞继续出现 1. 漏洞的起因 为了理解这个漏 ...

  6. How to keep Environment Variables when Using SUDO

    The trick is to add environment variables to sudoers file via sudo visudo command and add these line ...

  7. [Whole Web, Nods.js, PM2] Passing environment variables to node.js using pm2

    learn how to pass environment variables to your node.js app using the pm2 config file. This is usefu ...

  8. List environment variables from Command Prompt

    Request: List the environment variables from Command Promt To list one varibales , the syntax is lik ...

  9. [NPM] Execute npx commands with $npm_ Environment Variables

    We will incorporate npm specific environment variables when executing various npx commands. In our e ...

随机推荐

  1. jQuery中的表单对象属性过滤选择器(四、八)::enabled、:disabled、:checked、:selected

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  2. BeanUtils低依赖属性拷贝测试(一)

    javabean package entity; import java.util.Date; /** * 一个测试用: * student,javaBean * @author mzy * 一个标准 ...

  3. Struts2之Json插件的使用

    时间:2017-1-15 02:27 --普通方式处理异步请求:    ServletActionContext.getResponse().getWriter().print("aa&qu ...

  4. Python 3.10 is coming!

    看看Python 官网的文档 whatsnew,Python 3.10 已然距离我们越来越近了,然我们看看 Python 3.10 相较于 Python 3.9 有哪些改变吧 新特性 通过括号来组织多 ...

  5. Linkerd 2.10(Step by Step)—控制平面调试端点

    Linkerd 2.10 系列 快速上手 Linkerd v2 Service Mesh(服务网格) 腾讯云 K8S 集群实战 Service Mesh-Linkerd2 & Traefik2 ...

  6. 阿里云服务器部署mongodb

    在阿里云上买了个服务器,部署mongodb遇到一些坑,解决办法也是从网上搜集而来,把零零碎碎的整理记录一下. 服务器是:Alibaba Cloud Linux 下载安装 mongodb官网下载实在是太 ...

  7. Oracle环境配置之山路十八弯

    Oracle数据库的安装 背景: 因为疫情原因,只能在家上网课,学习Oracle的时候需要安装数据库,但是!! 安装的时候出现了报错: 无法检查指定的位置是否位于 CFS 上. 出来这个基本无解,这个 ...

  8. jenkins AWS CodeDeploy不停机部署

    此项目的特点是把Jenkins与CodeDeploy相结合做的CICD做的蓝绿发布,CI与CD 是分开的,CI构建完以后以BuildNumber的形式把war包存至AWS的S3桶中.同时在java项目 ...

  9. 20210712 noip12

    考场 第一次和 hzoi 联考,成功给 sdfz 丢人 尝试戴耳罩,发现太紧了... 决定改变策略,先用1h看题,想完3题再写. T1 一下想到枚举最大值,单调栈求出每个点能作为最大值的区间,然后以这 ...

  10. B. 2194: 快速傅立叶之二解题报告

    $$\begin{eqnarray}&c[k] = \sum_{i}^{n}a[i]b[i-k] \\&c[k] = \sum_{i}^{n}a[n-i]b[i-k] (倒序保存a) ...