当前位置 : 首页 » 文章分类 :  开发  »  FastAPI

FastAPI

FastAPI 学习笔记

fastapi/fastapi
https://github.com/fastapi/fastapi

官方中文文档
https://fastapi.tiangolo.com/zh/


简介

FastAPI 可以看做是 Starlette、Pydantic、OpenAPI 和 JSON Schema 粘合在一起:

  • FastAPI 使用 Pydantic 进行数据验证,并使用 Starlette 作为工具,使其与 Flask 相比快得惊人,具有与 Node 或 Go 中的高速 Web APIs 相同的性能
  • Starlette + Uvicorn 提供异步请求能力,这是 Flask 所缺乏的。
  • 与 Flask 不同,FastAPI 没有内置的 ASGI Web 服务器,因此需要像 Uvicorn 或 Daphne 这样的 ASGI 服务器。

安装

安装 fastapi

pip install fastapi

此外,还需要安装一个 ASGI 服务器,常用 uvicorn

pip install "uvicorn[standard]"

最简单的 FastAPI 应用

1、创建 fastapi_server.py

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)

2、启动 FastApi 服务
方法1,命令行中 python fastapi_server.py 启动
方法2,在 PyCharm 中点击 __main__ 旁边的运行图标启动,其实内部执行的也是 python fastapi_server.py
方法3,命令行中 uvicorn fastapi_server:app --reload 运行

uvicorn fastapi_server:app --reload 
INFO:     Will watch for changes in these directories: ['/Users/masi/git/my/py/web']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [35948] using WatchFiles
INFO:     Started server process [35975]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

其中:
fastapi_server 是 Python 模块名(即 Python 文件名)
app 是通过 app = FastAPI() 创建的应用对象
--reload 表示开启热更新,代码改动后会自动加载。仅在开发时使用该选项。

3、浏览器可打开 http://127.0.0.1:8000 可看到响应。


启动方式

命令行启动 uvicorn main:app(推荐)

FastAPI 官方文档推荐的方式
直接通过命令行参数调整(端口、主机、重载、工作进程等)
uvicorn main:app –host 0.0.0.0 –port 8000 –reload –workers 4
热重载​​:–reload 参数开发调试更方便

api启动 python main.py

# main.py 中的启动代码
if __name__ == "__main__":
    import uvicorn
    uvicorn.run("main:app", host="0.0.0.0", port=8000)

灵活性差​​:配置变更需修改代码
无法使用 –workers 多进程

python main.py 启动日志问题

日志配置如下

import logging
import os
from logging.handlers import TimedRotatingFileHandler

def setup_logging():
    """
    初始化全局日志配置。优先读取环境变量 LOG_FILE_DIR,未设置则写入项目根目录 log 目录。
    日志自动按天滚动,保留最近7天。
    """
    log_dir = os.environ.get("LOG_FILE_DIR")
    if log_dir:
        log_dir = os.path.abspath(log_dir)
    else:
        # 直接用当前工作目录下的 log 目录
        base_dir = os.getcwd()
        log_dir = os.path.join(base_dir, "log")
    os.makedirs(log_dir, exist_ok=True)
    logfile = os.path.join(log_dir, "pyapp.log")

    # 普通日志 handler
    file_handler = TimedRotatingFileHandler(logfile, when='midnight', backupCount=7, encoding='utf-8')
    stream_handler = logging.StreamHandler()
    default_fmt = logging.Formatter('%(asctime)s [%(threadName)s] %(levelname)s: %(message)s', '%Y-%m-%d %H:%M:%S')
    file_handler.setFormatter(default_fmt)
    stream_handler.setFormatter(default_fmt)

    root_logger = logging.getLogger()
    root_logger.setLevel(logging.INFO)
    root_logger.handlers.clear()
    root_logger.addHandler(file_handler)
    root_logger.addHandler(stream_handler)

    # uvicorn 访问日志 handler(与普通日志同格式)
    uvicorn_logger = logging.getLogger("uvicorn.access")
    uvicorn_logger.handlers.clear()
    access_file_handler = TimedRotatingFileHandler(logfile, when='midnight', backupCount=7, encoding='utf-8')
    access_stream_handler = logging.StreamHandler()
    access_file_handler.setFormatter(default_fmt)
    access_stream_handler.setFormatter(default_fmt)
    uvicorn_logger.addHandler(access_file_handler)
    uvicorn_logger.addHandler(access_stream_handler)

logger = logging.getLogger(__name__)
setup_logging()

问题:
uvicorn main:app 启动时,fastapi 的 http 访问日志可以写入 pyapp.log
python main.py 启动时,fastapi 的 http 访问日志在 pyapp.log 中看不到

原因:
通过 python main.py 启动时,uvicorn.run() 会​​内部初始化 Uvicorn​​,此过程会覆盖根日志记录器(root logger)的配置
命令行 uvicorn main:app –reload 启动时,应用(app)会先被导入,setup_logging() 会在 Uvicorn 初始化前执行

解决:
方法1(推荐),使用 uvicorn main:app 启动
方法2,__main__ 中,uvicorn.run(“main:app”, host=”0.0.0.0”, port=8000, reload=True, log_config=None) 增加 log_config=None,禁用 Uvicorn 的默认日志配置。


lifespan 生命周期

生命周期 lifespan
https://fastapi.tiangolo.com/zh/advanced/events/?h=#lifespan

FastAPI 的 lifespan 是一种用于统一管理应用生命周期事件(如启动和关闭)的机制,旨在替代旧版的 @app.on_event("startup")@app.on_event("shutdown") 方法。

lifespan 通过 ​​异步上下文管理器​​ 实现,允许在一个函数中集中处理应用的启动初始化和关闭清理逻辑。这种方式解决了旧版方法中资源管理割裂的问题,例如:

  • ​​启动阶段​​:加载配置文件、初始化数据库连接池、预加载机器学习模型等。
  • 关闭阶段​​:释放数据库连接、保存日志、清理缓存资源等。

@asynccontextmanager ​异步上下文管理器​

FastAPI 的 lifespan 生命周期需结合 @asynccontextmanager 装饰器定义异步上下文管理器,并通过 yield 分隔启动和关闭逻辑。

@asynccontextmanager 是 Python 标准库 contextlib 提供的装饰器,用于将一个异步生成器函数转换为 ​​异步上下文管理器​​。
其核心设计模式为:

  • yield 前​​:执行资源初始化(如连接数据库、加载模型)。
  • ​yield 后​​:执行资源清理(如关闭连接、释放内存)

@asynccontextmanager 装饰器适用于 ​​任何需要异步资源管理的场景​​,例如:

  • ​​数据库连接池​​:启动时创建连接池,关闭时释放。
  • ​​机器学习模型​​:预加载模型到内存,结束时卸载。
  • ​​网络请求会话​​:创建异步 HTTP 客户端,结束时关闭会话

定义 lifespan 函数

FastAPI 的 lifespan 是一种 ​​应用生命周期管理接口​​,要求开发者通过 异步上下文管理器 @asynccontextmanager 实现:
1、使用 @asynccontextmanager 装饰一个函数,​​函数签名符合要求​​:必须接收 app: FastAPI 参数
2、将该函数作为参数传递给 FastAPI(lifespan=...)

代码示例:

from contextlib import asynccontextmanager
from fastapi import FastAPI

@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动逻辑(如初始化数据库)
    print("应用启动,加载资源...")
    await init_database()
    yield
    # 关闭逻辑(如释放资源)
    print("应用关闭,清理资源...")
    await close_database()

app = FastAPI(lifespan=lifespan)

中间件(类似Java中的的Filter)

https://fastapi.tiangolo.com/zh/tutorial/middleware/


reload=True 导致重复初始化

--reloadreload=True 启用时,uvicorn 会监控代码变化并重新加载整个应用,直接写在 if __name__ == "__main__": 外的初始化逻辑会被执行多次。

下面代码中,print(“初始化”) 会被执行多次:

import uvicorn
from fastapi import FastAPI

print("初始化")

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

if __name__ == "__main__":
    uvicorn.run("fastapi_server:app", host="0.0.0.0", port=8000, reload=True)

启动日志:

初始化
INFO:     Will watch for changes in these directories: ['/Users/masi/git/my/py/web']
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [84530] using WatchFiles
初始化
初始化
INFO:     Started server process [84588]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

依赖注入

依赖项
https://fastapi.tiangolo.com/zh/tutorial/dependencies/


上一篇 Jinja 模板引擎

下一篇 Java-线程与线程池

阅读
评论
1.7k
阅读预计7分钟
创建日期 2025-04-21
修改日期 2025-06-24
类别

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论