@提示: 微信搜索【猿码记】回复 【fastapi】即可获取源码信息~
在这一篇文章中,对fastapi
框架和pydantic
进行了升级,然后就是各种不兼容,以后再也不敢轻易升级….
pydantic
:从1.10.11
升级到2.5.2
,这里有坑,里面有很多属性都给删除了,而且升级pydantic
后,fastapi
也必须升级,否则底层使用的pydantic
会有问题;
fastapi
: 从 0.94.0
升级到0.105.0
;
1.介绍 在大型项目中,良好的配置管理是确保系统可维护性和灵活性的关键,FastAPI
官方文档在设置和环境变量: https://fastapi.tiangolo.com/zh/advanced/settings/#_1 介绍了两种方式;
1.1 方式一:export
首先使用关键词export
设置配置值,如下:
export APP_NAME="FastAPI学习使用"
然后在代码中使用os.getenv("变量名","默认值")
获取
import os appName = os.getenv("APP_NAME" , "" )print (appName)
上述方式,适合配置比较少的情况,常用的还是下面方式
1.2 方式二: .env+pydantic
在日常工作中比较常用的还是通过.env
来设置配置,并把内容映射到pydantic
对应的模型上,方便读取和管理,下面以这个方式为主进行学习。
2. 安装依赖 2.1 安装python-dotenv
python-dotenv
是一个Python库,用于从文本文件中加载环境变量
$ pip install python-dotenv
2.2 安装pydantic_settings
$ pip install pydantic_settings
3.编写配置 3.1 编写.env APP_ENV =local APP_NAME =AI学习 APP_PORT =8080 APP_HOST =0.0.0.0 APP_VERSION =v1.0.0 APP_DEBUG =true JWT_ENABLE =false JWT_SECRET_KEY =abcd12345@abcdef JWT_ALGORITHM =HS256 JWT_EXPIRED =60 JWT_ISS =猿码记 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_DSN =redis://0.0.0.0:6379/0
3.2 编写配置模型 在包app/config
下,创建文件app_config.py
,内容如下:
from pydantic import RedisDsnfrom pydantic_settings import BaseSettingsclass 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
4.使用 4.1 创建配置实例 在文件app/config/__init__.py
编写代码如下
from dotenv import load_dotenvfrom .validate_template_config import validateChineseDict, keyErrorChineseDictfrom .app_config import * load_dotenv() appSettings = AppConfigSettings()
4.2 使用示例 在main.py
中使用
...from app.config import appSettings ...if __name__ == "__main__" : print (appSettings) uvicorn.run(server, host="0.0.0.0" , port=appSettings.app_port)
4.3 使用优化 根据官方文档介绍,如果通过上面方式使用配置,每次导入都会创建一个配置实例,而且从磁盘中读取文件通常是一项耗时的(慢)操作,所以尽可能的复用这个配置实例。文档推荐使用@lru_cache
装饰器,它只有在第一次调用它时,才会创建配置实例;
根据文档,我们修改app/config/__init__.py
代码,修改后如下:
from functools import lru_cachefrom dotenv import load_dotenvfrom .validate_template_config import validateChineseDict, keyErrorChineseDictfrom .app_config import *@lru_cache def getAppConfig () -> AppConfigSettings: load_dotenv() return AppConfigSettings() appSettings = getAppConfig()
4.4 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.讲解图
5.多环境管理 项目通常都会运行在多个环境,比如开发时运行本地环境、联调时运行测试环境、发布到线上是生产环境;
5.1 多个文件 .env # 默认为本地开发环境 .env.test # 测试环境 .env.prod # 生产环境
5.2 修改创建配置实例 在文件app/config/__init__.py
编写代码如下
import osfrom functools import lru_cacheimport argparsefrom dotenv import load_dotenvfrom .validate_template_config import validateChineseDict, keyErrorChineseDictfrom .app_config import *@lru_cache def getAppConfig () -> AppConfigSettings: """ 获取项目配置 """ parseCliArgument() runEnv = os.environ.get("APP_ENV" , "" ) print ("运行环境: " , runEnv) envFile = ".env" if runEnv != "" : envFile = f".env.{runEnv} " load_dotenv(envFile) return AppConfigSettings()def parseCliArgument (): """ 解析命令行参数 """ import sys if "uvicorn" in sys.argv[0 ]: print (sys.argv[0 ]) return parser = argparse.ArgumentParser(description="命令行参数" ) parser.add_argument("--env" , type =str , default="" , help ="运行环境" ) args = parser.parse_args() os.environ["APP_ENV" ] = args.env appSettings = getAppConfig()
@注意: 这里使用argparse
来接收命令行参数,根据不同的参数运行不通的环境
5.3 运行示例 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的文档来,不能传自定义参数