FastAPI 虚拟环境实战:用 uv 一条命令搭好隔离的 Python 开发环境
虚拟环境(Virtual Environment)是 Python 项目隔离依赖的基石,避免不同项目间的包版本互相污染。本文以 FastAPI 官方文档 为骨架,结合仓库内的安装文档、FastAPI CLI 文档 与 pyproject.toml 源码配置,手把手演示如何用 uv 一键创建 FastAPI 项目、自动生成虚拟环境并启动开发服务器,读完即可掌握一套从零到能跑的最小实战流程。
为什么 Python 项目需要虚拟环境
当你在机器上安装 Python 包(比如 pip install fastapi)时,这些包会默认进入系统级或用户级的全局目录。一旦同时维护多个 Python 项目,就会遇到经典问题:
- 项目 A 需要
pydantic的某个版本,项目 B 需要另一个不兼容的版本,二者会互相冲突; pip install后包的版本被悄悄改动,可能导致某个项目悄悄「坏掉」;- 升级系统或全局环境时,无法预测会影响到哪些正在运行的项目。
虚拟环境正是为了解决这个问题:它为每个项目单独划出一份 Python 解释器与包安装目录(FastAPI 生态中默认放在项目内的 .venv 目录),项目之间彼此隔离、互不干扰。官方文档的原话是:当你在 Python 项目中工作时,应当为每个项目使用一个虚拟环境来隔离它所安装的包。
虚拟环境本身只是一个概念与约定:它依托 Python 官方 venv 模块或第三方工具(如 virtualenv、uv)创建,本质是「指向项目专属解释器与 site-packages 的环境」。作为 FastAPI 项目,文档给出了当前推荐做法——直接使用 uv 来同时管理项目、依赖和虚拟环境。
认识 uv:FastAPI 推荐的「一站式」项目管理器
uv 是新一代 Python 包与项目管理工具,文档明确建议:「对于 FastAPI 项目,我推荐使用 uv 来管理项目、其依赖及其虚拟环境」。相较传统 venv + pip 的工作流,uv 的核心优势在于自动化的环境托管:
- 在项目目录创建虚拟环境并自动放在
.venv; - 通过
pyproject.toml声明依赖,用uv.lock锁死精确版本,保证团队与生产环境可复现; - 配合
uv run直接在项目环境中执行命令,省去手动source .venv/bin/activate等激活步骤。
从本仓库自身的工程化配置也能印证这套生态:仓库根目录同时存在 pyproject.toml(依赖声明)与 uv.lock(依赖锁定),说明 FastAPI 自己的开发与发布同样基于 uv 管理。其中 pyproject.toml 还声明了 standard 可选依赖组,这正是下文中 uv add "fastapi[standard]" 会带入的那组「标配」依赖。
从零创建 FastAPI 项目:四步走
第一步:安装 uv
先按 uv 官方提供的安装方式完成 uv 的安装(支持大多数主流系统与包管理器,请参考其官方安装说明执行),然后确认命令可用:
$ uv --version
如果此前从未接触过 uv,也可以把后续要用到的核心子命令先记住:
| 命令 | 作用 |
|---|---|
uv init |
初始化一个新的 Python 项目 |
uv add |
向项目添加依赖并写入 pyproject.toml |
uv run |
在项目的虚拟环境中执行命令 |
uv sync |
依据 uv.lock 将环境同步到锁定版本 |
uv python |
管理 / 选择项目使用的 Python 解释器版本 |
第二步:初始化项目
创建项目并进入目录:
$ uv init awesome-project --bare
$ cd awesome-project
命令拆解(对照 Tutorial - User Guide 中「What these commands do」的解释):
uv init:创建全新 Python 项目;awesome-project:以该名称新建一个目录,项目创建在其中;--bare:只生成最精简的pyproject.toml,不额外生成示例main.py、README.md等脚手架文件——因为本教程后续步骤里你会自己创建应用文件。
第三步:添加 FastAPI
$ uv add "fastapi[standard]"
uv add 会完成三件关键工作:
- 自动选择系统上兼容的 Python 版本;如果没装,uv 会自动下载一个;
- 解析 FastAPI 及全部传递依赖的互相兼容版本并安装;
- 把精确版本记录进
uv.lock,使后续在任何机器上都能安装出完全一致的环境(这一过程在文档中称为「锁定项目依赖」)。
注意:
"fastapi[standard]"的引号不能省。文档与 README 都特别强调,加上引号可确保命令在所有终端(如 zsh 等对[有特殊解释的 shell)中正常工作。
[standard] 代表什么
[standard] 是 FastAPI 的「标准可选依赖组」。在 pyproject.toml 中可以清楚看到它封装的内容,其中与本仓库后端运行直接相关的包括:
| 依赖 | 用途 |
|---|---|
fastapi-cli[standard] |
提供 fastapi dev / fastapi run 命令行 |
uvicorn[standard] |
ASGI 服务器,附带 uvloop 高性能事件循环 |
starlette、pydantic |
FastAPI 的两大核心依赖(web 与数据部分) |
httpx |
提供 TestClient 测试能力 |
jinja2 |
渲染 HTML 模板 |
python-multipart |
解析表单与文件上传 |
email-validator |
校验 email 字段 |
pydantic-settings |
应用配置(settings)管理 |
pydantic-extra-types |
额外的 Pydantic 数据类型 |
对应的可选安装形态(在 pyproject.toml 中同样有定义,README 亦给出说明):
uv add fastapi:只装核心框架,不带任何可选依赖;uv add "fastapi[standard]":标准全套(本文推荐),开箱即用;uv add "fastapi[standard-no-fastapi-cloud-cli]":标准依赖但不含fastapi-cloud-cli。
第四步:创建应用文件并运行
此时项目里还没有代码。创建 main.py(可参考 index.md 的完整示例):
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
在项目根目录启动开发服务器:
$ uv run fastapi dev
终端会输出类似下面的启动信息:
╭────────── FastAPI CLI - Development mode ───────────╮
│ Serving at: http://127.0.0.1:8000 │
│ API docs: http://127.0.0.1:8000/docs │
│ Running in development mode, for production use: │
│ fastapi run │
╰─────────────────────────────────────────────────────╯
随后打开浏览器访问 http://127.0.0.1:8000/items/5?q=somequery,即可看到 JSON 响应;访问 http://127.0.0.1:8000/docs 可查看 Swagger UI 交互式文档。
uv 的自动化:无需手动「创建 + 激活」环境
传统 venv + pip 流程要求你先 python -m venv .venv 创建环境,再 source .venv/bin/activate 激活它。而 uv 完全接管了这些步骤——官方文档明确指出:
uv会自动为项目创建虚拟环境,你不需要自己去创建或激活一个环境。
实际操作中你可以这样验证:执行 uv add 后,项目根目录下会出现一个 .venv 目录;uv add 在 pyproject.toml 中登记 FastAPI 的同时,也把依赖装进了 .venv。
用 uv run 在项目环境内执行命令
需要「在项目虚拟环境里执行命令」时,最干净的方式是 uv run,例如:
$ uv run fastapi dev
它与「手动激活环境后再执行 fastapi dev」等价,但不需要先激活。这也是一段可独立使用的运行模式:fastapi 命令内部调用 Uvicorn 来加载 ASGI 应用。仓库中该命令的注册位置见 pyproject.toml(fastapi = "fastapi.cli:main"),即安装 fastapi[standard] 后终端里就有了 fastapi 可执行程序。
需要额外加装依赖(例如 ASGI 服务器或工具库)时,继续用 uv add:
$ uv add "uvicorn[standard]"
已声明过的依赖要重装到锁定版本,则用:
$ uv sync
日常开发中还可以把常见的多命令串联起来:
$ uv run fastapi dev main.py
进入开发与生产的不同运行姿态
用 uv 管理好环境后,还需要区分 FastAPI 应用在「开发」与「生产」两种场景下的启动命令(详见 FastAPI CLI 文档):
- 开发模式
fastapi dev:默认开启自动重载(auto-reload),改完代码服务器自动刷新;默认只监听127.0.0.1,仅本机可访问,适合本地迭代。该模式资源开销更大、稳定性略低,只用于开发。 - 生产模式
fastapi run:默认关闭自动重载,监听0.0.0.0(全部网卡),可对外提供服务,适合容器与服务器部署。手动部署的完整讲解可参考 deployment/manually.md。
同时,fastapi 命令默认会尝试在 main.py 中自动探测名为 app 的 FastAPI 实例;如果项目结构更复杂(例如应用位于 backend/main.py),可在 pyproject.toml 中显式声明入口:
[tool.fastapi]
entrypoint = "backend.main:app"
仓库里能看到的工程化证据
本文所述工作流并非孤例,仓库内多份材料相互印证:
- README.md 的安装章节同样以
uv add "fastapi[standard]"作为首选安装方式; - Tutorial - User Guide 详细拆解了
uv init --bare、uv add、.venv生成与uv.lock锁定的过程; - pyproject.toml 定义了
standard/standard-no-fastapi-cloud-cli/all三组可选依赖及fastapi控制台入口; - 仓库根目录的 uv.lock 表明 FastAPI 自身的开发环境正是由 uv 管理依赖与虚拟环境。
这些共同说明:「uv + 虚拟环境」不是可选技巧,而是官方推荐的 FastAPI 项目标配工作流。
备选方案:python -m venv + pip
如果某些场景下必须回到传统工具链(例如受网络或公司政策限制无法安装 uv),官方文档也给出等价思路:手动创建一个虚拟环境并激活,再在环境内执行 pip install "fastapi[standard]",即:
$ python -m venv .venv
$ source .venv/bin/activate # Windows 下为 .venv\Scripts\activate
$ pip install "fastapi[standard]"
$ fastapi dev
这一分支路径的更多细节,可以进一步阅读官方《Virtual Environments guide》了解激活机制与 python -m venv / pip 的完整流程。需要提醒的是,手动管理环境意味着你也要自己负责环境激活、依赖升级与版本复现,相比之下 uv 自动化管理的体验更省心,这也是官方文档把它列为首选的原因。
小结
至此,一条完整的 FastAPI 最小工程链路已经跑通:
- 安装 uv;
uv init awesome-project --bare初始化最简项目;uv add "fastapi[standard]"自动建环境、装依赖、生成锁文件;- 编写
main.py,用uv run fastapi dev启动开发服务器; - 生产环境换用
uv run fastapi run,并将复杂目录结构通过pyproject.toml的[tool.fastapi] entrypoint显式声明。
整条链路全程无需手动创建或激活虚拟环境——这正是 uv 针对 FastAPI 项目推荐工作流的核心价值。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00