02 · Python 工程化
写脚本很快,写"能长期维护、能上生产、能协作"的 Python 需要工程化。本篇用 npm / TypeScript / Jest / ESLint 的熟悉心智,讲虚拟环境、依赖锁定、类型检查与测试怎么落地。
速览卡
| 项 | 内容 |
|---|---|
| 一句话定位 | 把 Python 从"脚本"升级为"工程"的工具链 |
| 核心内容 | venv/uv/poetry、pyproject、mypy、pytest、ruff |
| 读完能回答 | 装依赖为什么不先建虚拟环境?mypy 和 TS 类型检查差在哪? |
| 相关板块 | E01 Python 基础 | C09 服务端语言上手 | C11 后端测试 |
工具版本变化快
[易变],具体命令以官方文档为准,本篇给选择与心智。
一、虚拟环境:为什么 npm 里没这个烦恼
text
Node:npm install 装到项目 node_modules,天然隔离
Python:pip install 默认装到全局 site-packages,项目之间互相污染| 方案 | 定位 | 适用 |
|---|---|---|
venv | Python 自带 | 最小项目,先跑起来 |
uv | 新一代全能工具 | 新项目推荐,快且省心 |
poetry | 完整项目管理 | 要发包 / 团队约束严格 |
心智模型:venv 就是给每个项目一个独立的
site-packages,等价于 Node 的node_modules。先建环境再装依赖是铁律。
二、依赖管理:从 requirements 到 lock
| 概念 | 对应前端 | 说明 |
|---|---|---|
requirements.txt | 不锁版本的依赖清单 | 记录顶层依赖 |
| 锁文件 | package-lock.json | 锁定每个包的精确版本 |
pyproject.toml | package.json | 项目元数据 + 依赖 + 构建配置 |
前端用
pnpm-lock.yaml保证"任何人装的都一样",Python 同样要锁版本,否则"我本地能跑你不行"。
三、类型检查:注解不等于 TS
python
def add(a: int, b: int) -> int:
return a + b| 对比 | TS | Python |
|---|---|---|
| 类型由谁执行 | 编译期 | 运行时不校验 |
| 谁检查 | tsc | mypy / pyright |
| 不跑会怎样 | 编译报错 | 静默通过,直到运行出错 |
最关键的差异:Python 注解只是"文档"。不跑
mypy,等于any满天飞。工程化第一步就是 CI 里强制跑 mypy。
四、测试:pytest 替代 Jest
python
# test_math.py
def add(a, b):
return a + b
def test_add():
assert add(1, 2) == 3| 概念 | Jest | pytest |
|---|---|---|
| 断言 | expect(x).toBe(y) | assert x == y |
| 发现测试 | 按约定 | 按 test_ 前缀 / test_*.py |
| 参数化 | it.each | @pytest.mark.parametrize |
| Mock | jest.mock | monkeypatch / pytest-mock |
pytest 的
assert直接用 Python 语法,没有 Jest 那套断言库;测试文件命名与函数命名都有约定,扫描即用。
五、代码质量:ruff 一站式
text
ruff check . # 等价 ESLint:静态问题
ruff format . # 等价 Prettier:统一格式前端是 ESLint + Prettier 两件套,Python 用 ruff 一个工具全包,配置写在 pyproject.toml 里。
六、一个最小工程骨架
text
my_project/
├── pyproject.toml # 元数据 + 依赖 + ruff/mypy 配置
├── uv.lock # 锁文件(等价 package-lock)
├── src/my_project/ # 源码包
├── tests/ # 测试目录
└── .venv/ # 虚拟环境从
uv init开始,一路补齐依赖、测试、类型检查,就是最小可协作工程。
七、自检清单
- [ ] 知道必须先建虚拟环境,能解释为什么
- [ ] 能说出 venv / uv / poetry 的定位差异
- [ ] 知道锁文件为什么必要(对照 lockfile)
- [ ] 能解释"注解不等于类型安全"与 mypy 的关系
- [ ] 会用 pytest 写并跑第一个测试
- [ ] 知道 ruff 一站式替代 ESLint + Prettier
八、常见误区
| 误区 | 事实 |
|---|---|
"pip install 装到全局没关系" | 项目一多就互相污染,必须隔离 |
| "写了类型注解就安全" | 不跑 mypy 等于没写 |
| "pytest 必须学一套断言库" | 直接用 assert,只有进阶才需要插件 |
| "requirements.txt 够了" | 不锁版本就无法复现环境 |
九、动手练习
练习 A:搭一个工程
用 uv init 建项目,添加一个依赖并运行,观察生成的 pyproject.toml 与 uv.lock。
练习 B:接入 mypy
给 E01 里的某个函数写注解,故意传错类型,跑 mypy 看它报什么,对比 tsc 的行为。
练习 C:写三个测试
针对一个纯函数写三个 pytest 用例(含边界),跑 pytest 验证并通过。
相关文档
本区
- 01 · Python 语言基础与 TS 对照 —— 语法与心智迁移
- 03 · Python 异步与并发 —— 工程里的并发选择
后端区(Python 的主要去处)
- 09 · 服务端语言上手:FastAPI + Python —— Python 后端工程实践
- 11 · 后端测试实战:单元/接口/集成 —— 测试策略的完整版
速查
- 11 · Python 速查 —— 常用语法与命令速查