Python 进阶手册
实战
综合项目¶
看懂和会用之间隔着大量的练习。下面 6 个项目按学习阶段排列,每个都覆盖了若干章节的知识点。每个项目都给出了需求、验收标准和提示,但没有给完整答案:卡住时回到对应章节找思路,这正是练习的意义。
做项目的方法
项目一:命令行记账本¶
阶段:一、核心语言 知识点:dataclass、Enum、pathlib、json、argparse、datetime、异常处理
一个记录个人收支的命令行工具,数据保存在 JSON 文件里。
$ ledger add -50 --category food --note "午饭"
$ ledger add 8000 --category salary
$ ledger list --month 2026-09
$ ledger report --month 2026-09
收入 8000.00 | 支出 50.00 | 结余 7950.00
food 50.00 100.0%
需求
add:金额(正数收入、负数支出)、分类、备注、日期(默认今天)list:按月份、分类筛选,按日期排序report:某月的收入、支出、结余,以及支出按分类的占比delete ID:删除一条记录
验收标准
- 金额用
Decimal存储和计算,JSON 里存成字符串 - 数据文件不存在时自动创建;文件损坏时给出清楚的错误信息,而不是打印一段 traceback
- 分类用
Enum或者可配置的列表,输入不存在的分类时报错并列出可选项 - 核心逻辑(统计、筛选)和命令行、文件读写分开,并有测试
进阶挑战
- 支持导出 CSV、从银行账单 CSV 导入
- 把存储换成
sqlite3,要求命令行代码一行都不用改(提示:定义一个存储的 Protocol)
项目二:大日志文件分析器¶
阶段:一、核心语言 知识点:生成器管道、re、Counter、itertools、heapq、性能
分析 Nginx 访问日志(可以自己写一个脚本生成几百万行的测试数据)。
需求
- 统计:总请求数、各状态码数量、访问最多的前 10 个 URL 和 IP、每分钟的请求数
- 找出响应时间最慢的前 20 个请求
- 支持
.gz压缩的日志文件,支持同时分析多个文件 - 支持按时间范围过滤
验收标准
- 使用生成器管道处理,内存占用和文件大小无关(处理 1GB 的文件,内存不超过 100MB)
- 格式错误的行不会让程序崩溃,最后报告跳过了多少行
- 用
cProfile找出最慢的环节并优化,记录优化前后的耗时
进阶挑战
- 用
ProcessPoolExecutor并行处理多个文件,再合并统计结果(Counter支持相加) - 支持
tail -f模式:实时追踪一个正在写入的日志文件,每 5 秒刷新一次统计
项目三:带缓存和重试的异步爬虫¶
阶段:三、并发 知识点:asyncio、TaskGroup、Semaphore、超时、装饰器、httpx
从一个起始 URL 开始,抓取同一个域名下的页面,提取标题和链接。
需求
- 同时最多 N 个请求,每个请求有超时,失败时指数退避重试
- 不重复抓取同一个 URL;限制最大深度和最大页面数
- 遵守
robots.txt - 把结果保存为 JSON Lines(每行一个 JSON 对象)
验收标准
- 重试逻辑写成一个异步装饰器
@retry(times=3, exceptions=(httpx.TransportError,)) - 按 Ctrl+C 时能优雅退出:取消所有任务、保存已抓取的结果
- 用本地的
http.server或 mock 的传输层写测试,测试不访问真实网络
进阶挑战
- 增加对每个域名的速率限制(每秒最多 K 个请求)
- 支持断点续爬:重启后跳过已抓取的 URL
项目四:插件式任务调度器¶
阶段:二、三 知识点:__init_subclass__、Protocol、类型标注、threading 或 asyncio、logging
一个轻量的定时任务调度器,任务以插件的形式定义。
需求
- 定义
Task子类时自动注册(__init_subclass__),支持every="30s"/"10m"/"1h"这样的间隔 - 调度器按间隔运行任务,同一个任务上一次还没跑完时不重复启动
- 任务失败时记录日志并按策略重试,不影响其他任务
- 提供一个查看各任务状态(上次运行时间、耗时、是否成功)的命令
验收标准
- mypy strict 模式无错误
- 调度逻辑可以在测试中用"假时钟"驱动,不需要真的等待
- 支持从某个目录自动加载插件模块(
importlib)
进阶挑战
- 支持 cron 表达式
- 任务状态持久化到 SQLite,重启后恢复
项目五:迷你键值数据库¶
阶段:三、四 知识点:asyncio 网络编程、协议设计、持久化、测试、性能
实现一个类似简化版 Redis 的内存键值数据库,通过 TCP 提供服务。
需求
- 用
asyncio.start_server实现服务器,支持多个客户端同时连接 - 命令:
GET、SET、DEL、EXISTS、INCR、EXPIRE、TTL、KEYS pattern - 持久化:定期把数据快照写到磁盘(先写临时文件再原子地
rename),启动时加载 - 提供一个 Python 客户端库,支持
async with Client(...) as c: await c.set("k", "v")
验收标准
- 命令解析用
match语句 - 端到端测试:测试里启动服务器,用客户端库验证各命令
- 能承受 1000 个并发连接(写一个压测脚本验证)
进阶挑战
- 支持追加日志(AOF)持久化,崩溃后不丢数据
- 支持发布订阅(
SUBSCRIBE/PUBLISH)
项目六:发布一个自己的库¶
阶段:四、工程化 知识点:打包、文档、CI、语义化版本、类型标注
挑一个你在前面项目里写过的、有复用价值的模块(比如重试装饰器、日志解析器、配置加载器),把它发布成一个真正的库。
需求
- 完整的
pyproject.toml,支持 Python 3.12 及以上 - 公开 API 有完整的类型标注,并附带
py.typed标记文件 - README 包含安装、快速开始、API 说明
- GitHub Actions:在多个 Python 版本上跑 ruff、mypy、pytest;打标签时自动发布
- 用 MkDocs 写一个文档站点(就像你正在看的这个)
验收标准
- 在一个全新的虚拟环境里
uv add 你的库后,按 README 能直接用起来 - 测试覆盖率 90% 以上
- 版本号遵循语义化版本,维护 CHANGELOG
进阶挑战
- 先发布到 TestPyPI 验证流程,再发布到正式的 PyPI
- 请朋友用一用,根据反馈发布 0.2.0
发现错误或有更好的写法?在 GitHub 上编辑此页提交问题