← Back to 文字

uv 与项目初始化

本文来自《AI 应用开发课程》月份 1 课程文档,已整理为网站文章版本。

学习目标

学完本节后,你应当能够:

  • 使用 uv 初始化 Python 项目。
  • 理解虚拟环境、依赖、锁文件的作用。
  • 创建月份 1 的第一个练习项目 llm_api_lab

前置知识

  • 已完成 01-Python语言补位/ 模块

1. 为什么月份 1 统一用 uv

因为它同时解决了几个问题:

  • 创建项目
  • 安装依赖
  • 管理虚拟环境
  • 管理锁文件
  • 统一运行命令

对初学者来说,这比混用 pipvenvrequirements.txtpoetry 更容易保持稳定。

2. 初始化项目

进入你的工作目录后执行:

uv init llm_api_lab
cd llm_api_lab

预期结果:

  • 目录被创建
  • 出现 pyproject.toml
  • 出现项目入口文件

3. 安装依赖

执行:

uv add httpx pydantic python-dotenv
uv add --dev pytest ruff

说明:

  • httpx:后面用于异步 HTTP 请求
  • pydantic:做数据建模和校验
  • python-dotenv:加载 .env
  • pytest:测试
  • ruff:代码检查

4. 同步依赖与运行

执行:

uv sync
uv run python --version

预期结果:

  • uv 创建并使用项目自己的环境
  • 能在该环境里运行 Python

5. 推荐初始化目录

将项目逐步整理成:

llm_api_lab/
├── app/
│   ├── __init__.py
│   ├── config.py
│   ├── models.py
│   └── services/
├── tests/
├── .env.example
├── README.md
└── pyproject.toml

6. 为什么一开始就要放 README 和 tests

因为月份 1 练的是“工程化”,不是“随手试验”。

  • README.md 保证可重现
  • tests/ 保证可回归

7. 第一个运行脚本

创建一个最小入口,例如 main.py

def main() -> None:
    print("llm_api_lab initialized")


if __name__ == "__main__":
    main()

执行:

uv run python main.py

8. 实操任务

  1. 初始化 llm_api_lab
  2. 安装依赖
  3. 创建 app/tests/.env.exampleREADME.md
  4. 运行第一个入口脚本

9. 自测题

  1. uv 相比只用 pip 带来了哪些统一能力?
  2. 为什么不能把月份 1 所有内容都写在一个项目里?
  3. 为什么 README.md 从第一天就要存在?

10. 作业与验收

验收标准:

  • 项目能用 uv 成功运行
  • 依赖安装完成
  • 目录结构清晰
  • 你能说明每个依赖准备干什么

11. 常见错误

  • 初始化后不进入项目目录就开始装依赖
  • 把所有练习写在顶层目录
  • 不写 .env.example

12. 本章与前文关系

前面的 Python 语言补位模块,让你具备了“能写、能读、能改”月份 1 代码的最低语言基础。本章开始,重点从“语言能力”切换到“项目能力”。

这一章要解决的核心问题是:

当你不再只是写一个 .py 脚本,而是准备做一个可迭代的小项目时,应该如何初始化它?

这一步是后面所有工程化内容的起点。

13. 本章在研发助手项目中的位置

研发助手项目最终会有:

  • 独立项目目录
  • 明确依赖
  • 可复现环境
  • README
  • .env.example
  • 测试目录

而这些都从本章开始建立。也就是说,第 4 周综合项目其实不是凭空起一个大工程,而是在本章的项目初始化方式上不断扩展。

14. 为什么月份 1 统一使用 uv

并不是因为 uv 是唯一正确选择,而是因为月份 1 需要一个足够统一、足够稳定、足够轻量的 Python 项目管理方式。

你可以把 uv 理解为帮你统一做了几件原本容易散落的事:

  • 创建项目
  • 管理依赖
  • 管理虚拟环境
  • 运行命令
  • 维护锁定依赖版本

这对初学者尤其重要,因为它减少了“工具链分裂”带来的认知负担。

15. uv、虚拟环境、依赖锁定分别在解决什么问题

uv

负责把“项目管理”这件事统一起来。

虚拟环境

负责让每个项目有自己的依赖隔离空间,避免不同项目互相污染。

锁定依赖

负责让你和别人、以及未来的自己,在尽量一致的依赖版本上运行项目。

如果这三者不分清,很多人会误以为:

  • 装上依赖就等于完成工程化

实际上,工程化的重点是“稳定、清晰、可复现”。

16. 错误示例 vs 正确示例

错误示例:随手在任何目录安装依赖

pip install httpx fastapi pytest

问题:

  • 你很快会忘记这个环境到底服务于哪个项目
  • 不同项目之间会相互污染
  • 难以重现依赖版本

正确示例:先初始化项目,再在项目内部管理依赖

uv init llm_api_lab
cd llm_api_lab
uv add httpx pydantic python-dotenv
uv add --dev pytest ruff

这个顺序的价值不是“命令更整齐”,而是你从一开始就在建立项目边界。

17. 完整文件级示例:一个最小教学型项目骨架

下面不是要你一次性实现所有内容,而是让你看到月份 1 项目初始化完成后,一个健康的最小骨架应该长什么样。

llm_api_lab/
├── app/
│   ├── __init__.py
│   ├── config.py
│   ├── models.py
│   └── services/
│       └── __init__.py
├── tests/
│   └── __init__.py
├── .env.example
├── README.md
├── main.py
└── pyproject.toml

main.py

"""月份 1 llm_api_lab 的最小入口。"""


def main() -> None:
    print("llm_api_lab initialized")


if __name__ == "__main__":
    main()

.env.example

DEEPSEEK_API_KEY=
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-chat

README.md

# llm_api_lab

月份 1 第 1 周练习项目,用于承载 Python 工程化与最小 LLM 调用练习。

18. 逐段解释这组项目骨架

为什么现在就有 app/

因为月份 1 后面的内容最终都会进入项目内部模块。你现在提前把主目录建好,后面就不会一直在顶层目录乱堆文件。

为什么现在就有 tests/

因为测试不是“最后有空再补”。从第一周开始把测试目录放进去,可以帮助你形成默认工程习惯。

为什么现在就有 .env.example

因为你后面一定会接 API Key。提前把配置承载方式固定下来,会让后面每一章更顺。

为什么 README.md 这么早就存在

因为可重现性是工程的一部分。哪怕只是第 1 周练习项目,也应该让未来的自己知道它是干什么的。

19. pyproject.toml 到底是什么

如果用一句话概括:

pyproject.toml 是 Python 项目的核心配置文件。

在月份 1,你不需要掌握它的全部生态历史,但至少要理解它的作用:

  • 描述项目元信息
  • 记录依赖
  • 作为工具配置入口

后面 ruff、测试和项目信息都会围绕它展开。

20. 从最小初始化到工程项目的递进

第一步:能创建项目

有目录、有入口、有依赖管理。

第二步:能承载配置与模型

加入 config.pymodels.py

第三步:能承载服务逻辑

加入 services/、后续加入 clients/

第四步:能对外暴露

第 3 周接上 FastAPI,第 4 周进入综合项目。

你要意识到:uv init 不是终点,而是一个结构化项目生命周期的起点。

21. 调试与排错:本章常见问题

问题一:不在项目目录里执行命令

会导致依赖装到错误位置,或者配置文件不在你以为的目录。

问题二:顶层目录和项目目录混淆

例如你以为自己在 llm_api_lab 里,实际还在 month1-workspace 顶层。

问题三:以为项目骨架是“多余的形式主义”

这是典型误解。月份 1 后面的项目整洁度,几乎都取决于这里的骨架是否稳定。

22. 本章完成后你应该具备的能力

完成本章后,你应当做到:

  1. 能独立初始化一个月份 1 练习项目。
  2. 能解释为什么要独立项目目录。
  3. 能说明 pyproject.tomlREADME.md.env.example 为什么一开始就要存在。
  4. 能搭出后续可扩展的目录骨架。

23. 如果你卡在这里,先回看哪几章

24. 从本章过渡到下一章的桥接说明

接下来进入 02-ruff日志env配置.md

本章只是把“项目壳子”搭起来了。下一章要往这个壳子里放入真正的工程基础设施:环境变量、日志和代码检查。也就是从“有项目目录”升级到“项目具备最小工程感”。

Fin