@提示: 微信搜索【猿码记】回复 【fastapi】即可获取源码信息~
在这一篇文章中,对fastapi
框架和pydantic
进行了升级,然后就是各种不兼容,以后再也不敢轻易升级....
pydantic
:从 1.10.11
升级到 2.5.2
,这里有坑,里面有很多属性都给删除了,而且升级 pydantic
后, fastapi
也必须升级,否则底层使用的 pydantic
会有问题; fastapi
: 从 0.94.0
升级到 0.105.0
; 在大型项目中,良好的配置管理是确保系统可维护性和灵活性的关键,FastAPI
官方文档在设置和环境变量: https://fastapi.tiangolo.com/zh/advanced/settings/#_1介绍了两种方式;
export
首先使用关键词export
设置配置值,如下:
export APP_NAME="FastAPI学习使用"
然后在代码中使用os.getenv("变量名","默认值")
获取
import os
appName = os.getenv("APP_NAME", "")
print(appName)
上述方式,适合配置比较少的情况,常用的还是下面方式
.env+pydantic
在日常工作中比较常用的还是通过.env
来设置配置,并把内容映射到pydantic
对应的模型上,方便读取和管理,下面以这个方式为主进行学习。
python-dotenv
python-dotenv
是一个Python库,用于从文本文件中加载环境变量
$ pip install python-dotenv
pydantic_settings
$ pip install pydantic_settings
# -------- 服务配置信息 --------
APP_ENV=local
APP_NAME=AI学习
APP_PORT=8080
APP_HOST=0.0.0.0
APP_VERSION=v1.0.0
APP_DEBUG=true
# -------- jwt配置 --------
# 是否开启jwt
JWT_ENABLE=false
# 秘钥
JWT_SECRET_KEY=abcd12345@abcdef
# 算法
JWT_ALGORITHM=HS256
# 过期时间(单位:分钟)
JWT_EXPIRED=60
# 签发人
JWT_ISS=猿码记
# 不校验JWT token的路由
JWT_NO_CHECK_URIS=/,/apidoc,/openapi.json,/api/user/login,/favicon.ico
# -------- 数据库配置 --------
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASSWORD=root
DB_DATABASE=test
# -------- redis配置 --------
REDIS_DSN=redis://0.0.0.0:6379/0
在包app/config
下,创建文件app_config.py
,内容如下:
from pydantic import RedisDsn
from pydantic_settings import BaseSettings
class AppConfigSettings(BaseSettings):
"""应用配置"""
app_name: str = "FastAPI学习"
app_port: int = 8080
app_env: str = "dev"
app_debug: bool = False
"""jwt配置"""
jwt_enable: bool = False
jwt_secret_key: str = "12345789@98765431"
jwt_algorithm: str = "HS256"
jwt_expired: int = 30
jwt_iss: str = "猿码记"
jwt_no_check_uris: str = ""
"""数据库配置"""
db_host: str
db_port: int
db_user: str
db_password: str
db_database: str
"""redis配置"""
redis_dsn: RedisDsn = None
在文件app/config/__init__.py
编写代码如下
from dotenv import load_dotenv
from .validate_template_config import validateChineseDict, keyErrorChineseDict
from .app_config import *
# 加载 .env 文件
load_dotenv()
# 实例化配置模型
appSettings = AppConfigSettings()
在main.py
中使用
...
# 导入配置
from app.config import appSettings
...
if __name__ == "__main__":
# 打印配置
print(appSettings)
# 这里使用端口是.env 中配置的
uvicorn.run(server, host="0.0.0.0", port=appSettings.app_port)
根据官方文档介绍,如果通过上面方式使用配置,每次导入都会创建一个配置实例,而且从磁盘中读取文件通常是一项耗时的(慢)操作,所以尽可能的复用这个配置实例。文档推荐使用@lru_cache
装饰器,它只有在第一次调用它时,才会创建配置实例;
根据文档,我们修改app/config/__init__.py
代码,修改后如下:
from functools import lru_cache
from dotenv import load_dotenv
from .validate_template_config import validateChineseDict, keyErrorChineseDict
from .app_config import *
@lru_cache
def getAppConfig() -> AppConfigSettings:
# 加载 .env 文件,dotenv_path 变量默认是.env
load_dotenv()
# 实例化配置模型
return AppConfigSettings()
# 获取配置
appSettings = getAppConfig()
lru_cache
技术细节具体说明,可查看官方文档: https://fastapi.tiangolo.com/zh/advanced/settings/#lru_cache
@lru_cache
装饰器,相当于是缓存了函数结果,当相同入参请求时,返回的是缓存结果,不相同时则会重新计算结果,以下是官方给的代码示例和配套讲解图
a.代码示例
@lru_cache
def say_hi(name: str, salutation: str = "Ms."):
return f"Hello {salutation} {name}"
b.讲解图
项目通常都会运行在多个环境,比如开发时运行本地环境、联调时运行测试环境、发布到线上是生产环境;
.env # 默认为本地开发环境
.env.test # 测试环境
.env.prod # 生产环境
在文件app/config/__init__.py
编写代码如下
import os
from functools import lru_cache
import argparse
from dotenv import load_dotenv
from .validate_template_config import validateChineseDict, keyErrorChineseDict
from .app_config import *
@lru_cache
def getAppConfig() -> AppConfigSettings:
""" 获取项目配置 """
# 解析命令行参数
parseCliArgument()
# 读取运行环境
runEnv = os.environ.get("APP_ENV", "")
print("运行环境: ", runEnv)
# 默认加载.env
envFile = ".env"
# 运行环境不为空加载 .env 文件
if runEnv != "":
# 当是其他环境时,如测试环境: 加载 .env.test 正式环境: 加载.env.prod
envFile = f".env.{runEnv}"
# 加载配置
load_dotenv(envFile)
# 实例化配置模型
return AppConfigSettings()
def parseCliArgument():
""" 解析命令行参数 """
import sys
if "uvicorn" in sys.argv[0]:
# 使用uvicorn启动时,命令行参数只能按照uvicorn的文档来,不能传自定义参数,否则报错
return
# 使用 argparse 定义命令行参数
parser = argparse.ArgumentParser(description="命令行参数")
parser.add_argument("--env", type=str, default="", help="运行环境")
# 解析命令行参数
args = parser.parse_args()
# 设置环境变量
# uvicorn模式启动,读取的.env*里面的APP_ENV
os.environ["APP_ENV"] = args.env
# 创建配置实例
appSettings = getAppConfig()
@注意: 这里使用
argparse
来接收命令行参数,根据不同的参数运行不通的环境
a.使用python启动
# 默认环境 .env
$ python main.py
# 测试环境 .env.test
$ python main.py --env=test
# 生产环境 .env.prod
$ python main.py --env=prod
b.使用uvicorn启动
# 默认环境 .env
$ uvicorn main:server --port 8000 --env-file .env
# 测试环境 .env.test
$ uvicorn main:server --port 8001 --env-file .env.test
# 生产环境 .env.prod
$ uvicorn main:server --port 8002 --env-file .env.test
@注意: 使用uvicorn启动时,命令行参数只能按照uvicorn的文档来,不能传自定义参数
本文由 mdnice 多平台发布