首页
/ FastAPI 应用调试实战:直接在代码中运行 Uvicorn,并在 VS Code 与 PyCharm 中断点调试

FastAPI 应用调试实战:直接在代码中运行 Uvicorn,并在 VS Code 与 PyCharm 中断点调试

2026-09-07 14:13:28作者:裘旻烁

本文围绕 FastAPI 官方教程中的「调试(Debugging)」主题展开:教你如何在编辑器中把调试器直接挂到 FastAPI 应用上——先在应用代码里显式导入并调用 uvicorn.run() 启动服务器,再利用 __name__ == "__main__" 的机制保证服务只在直接运行文件时启动,最后在 Visual Studio Code 或 PyCharm 的调试器中启动程序并命中断点。读完本文,你将掌握一套完整的 FastAPI 本地调试工作流,并理解「直接在代码中启动 Uvicorn」与「命令行 fastapi dev 启动」两种方式的关系与适用场景。

VS Code 中调试 FastAPI 应用

为什么要在代码里直接调用 uvicorn

FastAPI 应用的常规运行方式是使用命令行工具启动 Uvicorn,例如 fastapi dev(该命令由 fastapi-cli 提供,入口封装见 fastapi/cli.py,其中在缺少 fastapi[standard] 依赖时会提示安装;pyproject.toml 中的 standard 依赖组包含了 uvicorn[standard] >=0.12.0)。

但调试场景有一个特殊需求:编辑器调试器(Debug Adapter)是通过启动一个 Python 进程来附加断点的,它要求你自己启动的解释器进程里运行着你的应用代码。如果服务器是由外部命令行工具拉起的,调试器很难与之关联。因此官方调试教程给出的做法很直接:在你的 FastAPI 应用里导入 uvicorn,并直接调用 uvicorn.run(),让服务器作为「当前脚本」的一部分启动。这样调试器只需要运行你的 Python 文件,就能断点命中请求处理逻辑。

在 FastAPI 应用中导入并直接运行 uvicorn

教程给出的完整可运行示例位于 docs_src/debugging/tutorial001_py310.py,内容如下:

import uvicorn
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def root():
    a = "a"
    b = "b" + a
    return {"hello world": b}


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

几个要点:

  • import uvicorn:Uvicorn 是 ASGI 服务器,uvicorn.run() 是它的编程式启动入口。注意它接收的是 应用对象 app(而非模块字符串),这正是本方案的关键——服务器在同一个解释器进程中启动;
  • host="0.0.0.0":监听所有网络接口,便于局域网或容器外的设备访问开发服务器;
  • port=8000:FastAPI 生态的默认开发端口;
  • 请求处理函数 root() 中只有几行普通 Python 代码(a = "a"b = "b" + a),这里就是在编辑器里设置断点的位置——当调试器启动该脚本后,任意 HTTP 请求打到 GET / 时都会停在断点处,可以查看/修改局部变量。

保存为 main.py 后,直接运行:

$ uv run python main.py

即可启动服务。此时 if __name__ == "__main__": 块内的 uvicorn.run(...) 会被执行,服务器在当前进程内启动。

深入理解 __name__ == "__main__"

if __name__ == "__main__": 是 Python 的模块保护惯用法,它的目的是让某段代码只在文件被直接执行时运行,而在文件被其他模块导入时不运行

直接执行文件时

假设文件名为 myapp.py,用如下命令运行:

$ uv run python myapp.py

Python 解释器会自动在该文件内部创建一个内置变量 __name__,其值为字符串 "__main__"。因此判断条件成立,这段代码:

    uvicorn.run(app, host="0.0.0.0", port=8000)

会被执行,服务器随之启动。

被其他模块导入时

这个行为不会发生。比如另有一个 importer.py

from myapp import app

# 其他一些代码

myapp 被导入时,myapp.py 内部自动创建的 __name__ 变量的值不是 "__main__",而是模块名 "myapp"。于是:

    uvicorn.run(app, host="0.0.0.0", port=8000)

不会被执行——导入方拿到的只是 app 对象,服务器是否启动完全由导入方决定。

这个机制对调试场景的意义在于:同一段代码可以兼容两种用法——

  • 开发调试时:python myapp.py 直接运行,进程内自带服务器,编辑器调试器可以直接接管;
  • 生产部署或测试时:from myapp import app 导入应用对象,交给外部进程管理器(如 fastapi run、Gunicorn/Uvicorn 的命令行多 worker 模式)去启动,避免导入即起服务器带来的端口冲突与进程混乱。

关于 __main____name__ 的更多细节,可以参考 Python 标准库文档中的 __main__ 章节(此处不提供外部链接,见 Python 官方文档「The Python Runtime → __main__ 模块」)。

用编辑器调试器运行你的代码

因为 Uvicorn 服务器是从你的代码内部直接启动的,你可以把整个 Python 程序(你的 FastAPI 应用)直接交给编辑器的调试器来运行,断点、变量监视、调用栈全部可用。

Visual Studio Code 的步骤

  1. 打开侧边栏的 Debug(调试)面板;
  2. 点击 「Add configuration...」
  3. 选择 「Python」
  4. 「Python: Current File (Integrated Terminal)」 方式运行调试器。

随后 VS Code 会启动你的 FastAPI 代码作为服务器,并会在你设置的断点处暂停,行为与普通 Python 脚本调试一致。

PyCharm 中调试 FastAPI 应用

PyCharm 的步骤

  1. 打开顶部 Run 菜单;
  2. 选择 Debug... 选项;
  3. 弹出一个上下文菜单;
  4. 选择要调试的文件(例如 main.py)。

PyCharm 会以调试模式启动该文件,你的 FastAPI 服务器随之运行,请求处理逻辑会在断点处暂停,便于逐行执行与检查状态。

两种编辑器的本质相同:调试器以调试模式启动 python main.py 这个进程,__name__ == "__main__" 判断成立,uvicorn.run() 在当前进程内启动 ASGI 服务器,随后每个进入路由处理函数的请求都会触发断点。

fastapi dev / fastapi run 的关系与选择建议

从源码结构看,仓库中的 fastapi/cli.py 只是把命令行入口委托给独立的 fastapi-cli 包(from fastapi_cli.cli import main),它负责按约定发现应用模块并拉起 Uvicorn。官方文档 docs/en/docs/fastapi-cli.md 说明了两种模式:

  • fastapi dev:开发模式,启动前会把环境变量 FASTAPI_ENV 设置为 development(若已设置则保留原值),便于应用启动代码选择开发友好行为;
  • fastapi run:生产模式。

两种启动方式对比:

方式 启动机制 是否天然支持编辑器断点 典型场景
代码内 uvicorn.run(app, ...) 当前进程内启动 ASGI 服务器 是——调试器直接启动该脚本进程 本地开发、断点调试
fastapi dev / fastapi run 外部 CLI 发现并启动应用 需额外配置「附加到已运行进程」或调试器启动参数 日常开发(带热重载)、生产部署

因此本文教程的价值在于:当你需要逐行断点调试请求处理逻辑、依赖关系或序列化行为时,把 if __name__ == "__main__": uvicorn.run(...) 这一行放进应用文件,用编辑器调试器直接跑当前文件,是成本最低、兼容性最好的路径。调试完成后,这行代码保留下来也不会影响 import app 式的部署方式——这正是 __name__ == "__main__" 惯用法的收益所在。

小结

  • 在 FastAPI 应用文件顶部 import uvicorn,并在 if __name__ == "__main__": 块中调用 uvicorn.run(app, host="0.0.0.0", port=8000),即可让服务器随脚本进程启动;
  • __name__ == "__main__" 保证:直接 python myapp.py 运行时启动服务器,被 from myapp import app 导入时则不启动,兼顾调试与部署两种用法;
  • VS Code 用 Debug 面板的 「Python: Current File (Integrated Terminal)」,PyCharm 用 Run → Debug... 选择目标文件,即可在断点处暂停 FastAPI 的请求处理代码;
  • 完整可运行示例见 docs_src/debugging/tutorial001_py310.py,教程原文见 docs/es/docs/tutorial/debugging.md
登录后查看全文
热门项目推荐
相关项目推荐