背景

  • 在许多情况下,应用程序可能需要一些外部设置或配置,例如密钥、数据库凭据、电子邮件服务凭据等。
  • 大多数这些设置都是可变的(可以更改),例如数据库 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. tomcat过滤器异常

    Connected to server[2019-11-25 04:40:58,976] Artifact DUBBO_BG:Web exploded: Artifact is being deplo ...

  2. python json demo

    值得注意的一点是,list类型的数据可以用[2,3]的方式定义,如"b" import json jsonData = '{"a":1,"b" ...

  3. etcd学习(8)-etcd中Lease的续期

    etcd中的Lease 前言 Lease Lease 整体架构 key 如何关联 Lease Lease的续期 过期 Lease 的删除 checkpoint 机制 总结 参考 etcd中的Lease ...

  4. idea字节码插件JClassLib——阅读JVM字节码

    idea字节码插件JClassLib--阅读JVM字节码 生成字节码文件并查看 查看字节码文件的方式:javac 文件名.java 即可生成.class文件,但是这种方式不方便 java:是运行字节码 ...

  5. Geode member发现机制

    Geode member发现机制 Apache Geode 为集群和客户端服务器间提供了多种member 发现机制,具体如下: Peer Member Discovery Standalone Mem ...

  6. 20210811 Dove 打扑克,Cicada 与排序,Cicada 拿衣服

    考场 开考感觉 T3 比较可做.T1 看上去不难但毫无思路. 先想了 25min T3,想到一个确定左端点,二分最长的右端点,甚至想到了用猫树维护区间 or and...上厕所回来发现假了,没有单调性 ...

  7. Linux制作根文件系统笔记

    测试平台 宿主机平台:Ubuntu 12.04.4 LTS 目标机:Easy-ARM IMX283 目标机内核:Linux 2.6.35.3 交叉编译器:arm-linux-gcc 4.4.4 Bus ...

  8. SpringBoot-初见

    目录 简单介绍 什么是SpingBoot? 微服务 单体应用架构 微服务架构 怎么构建微服务 第一个SpringBoot程序 官方网站快速构建 IDEA 代码 自动装配(要点) pom.xml 启动器 ...

  9. 物理机burp抓虚拟机包

    先设置网络连接为NAT模式. 这就相当于主机虚拟出一个网卡,虚拟机单独成为一个网段(相当于虚拟机为单独一台主机,物理机作为路由器网关使用),我将会在物理机,也就是这个"路由器"上设 ...

  10. 中心对称数 II

    中心对称数 II 1.题目描述 中心对称数是指一个数字在旋转了 180 度之后看起来依旧相同的数字(或者上下颠倒地看). 找到所有长度为 n 的中心对称数. 示例 : 输入: n = 2 输出: [& ...