跳转至

Week 2 · M6a · 打包与项目结构操作清单(周一 块 3)

用法:照顺序做,每完成一步把 [ ] 改成 [x],并把要求记录的输出/答案写在该步下面的"记录"里。 全程在仓库根目录 learn-python/ 执行命令(除特别说明)。 卡住 8 分钟以上再按 ai-guide.md 的模板提问。

0. 为什么要有这份清单

第 1 周的代码是"一堆脚本",第 2 周开始是"一个包"。包和脚本的区别不在于语法, 而在于:别人(和一个月后的你)能不能安装它、导入它、给它写测试、给它发版本


1. 核对 projects/kb/ 骨架

  • 打开 projects/kb/,逐个文件回答"它为什么存在":
文件 一句话作用(自己写,不要抄)
pyproject.toml
src/kb/__init__.py
src/kb/__main__.py
src/kb/cli.py
tests/test_cli.py
README.md
  • pyproject.toml 里指出这四段各自的作用:[project][project.scripts][build-system][tool.ruff.lint]
  • 回答:为什么代码放在 src/kb/ 而不是仓库根的 kb/?(关键词:假阳性导入、 "在仓库根能 import、装好后却不能")

记录:

(在这里写你的答案)

2. 同步环境并运行入口点

  • uv sync
  • uv run kb hello 小明
  • uv run python -m kb hello 小明
  • 回答:这两条命令分别是怎么找到代码的?(关键词:[project.scripts] 生成的 .venv/Scripts/kb.exe 包装器 / python -m 找到包的 __main__.py
  • 故意试一次 uv run python projects/kb/src/kb/cli.py,把报错抄下来,解释为什么会失败。

记录:

(在这里写你的答案与报错信息)

3. 构建 wheel 看看里面有什么

  • uv build --package kb
  • ouch list dist/kb-0.1.0-py3-none-any.whl(或解压到临时目录看)
  • 回答:wheel 里有 src/ 这一层目录吗?为什么?
  • rm -r dist(构建产物不进 Git,.gitignore 里应该已经有 dist/

记录:

(在这里写 wheel 的文件清单要点)

4. 确认"装好了"而不是"碰巧能 import"

  • uv run python -c "import kb, importlib.metadata as m; print(kb.__file__, m.version('kb'))"
  • 回答:importlib.metadata.version("kb") 读的是哪里的信息?和 kb.__version__ 有什么区别? 如果两者不一致会怎样?

记录:

(在这里写你的答案)

5. 给 kb 加一个 version 子命令并测试

  • 确认 src/kb/cli.py 里有 version 子命令(骨架已给);读懂它为什么在函数内部 才 from kb import __version__(提示:避免循环导入 + 启动更快)。
  • projects/kb/tests/test_cli.py 里补一条测试:CliRunner 调用 version, 断言输出里含 kb.__version__
  • uv run pytest projects/kb/tests/test_cli.py -q

记录:

(在这里写测试通过的输出)

6. PEP 723 单文件脚本

  • exercises/week2/w2_01_inline_script.py 顶部的 # /// script 块。
  • uv run exercises/week2/w2_01_inline_script.py(uv 会为它单独准备一个临时环境)
  • dependencies 里的 rich 删掉再跑一次,抄下报错,然后改回来。
  • 回答:什么时候用 PEP 723 单文件脚本,什么时候应该建一个包?

记录:

(在这里写你的答案)

7. 收尾

  • uv run ruff format exercises/week2 projects/kb
  • uv run ruff check exercises/week2 projects/kb
  • git add -A && git commit -m "chore: 核对 kb 骨架与打包流程"

自查(周测会考)

  1. src 布局解决了什么问题?
  2. [project.dependencies][dependency-groups].dev 的区别是什么?
  3. uv runuvxuv syncuv add 各自什么时候用?
  4. uv.lock 该不该进 Git?为什么?
  5. 为什么 2026 年不再写 setup.py 和手工维护的 requirements.txt