Poetry 从零到工程实践:小白系统笔记

Poetry 从零到工程实践:小白系统笔记

适合对象:刚开始接触 Python 项目管理、虚拟环境、依赖管理、pyproject.toml、Poetry、conda、Docker 的学习者。

写作方式:先讲原理,再举例子。

示例项目:本文统一使用通用示例,例如 blog-apiimage-classifierdata-toolkit,不使用任何具体业务项目。

版本背景:以 Poetry 2.x 的现代用法为主,同时解释旧写法为什么还会出现。


目录

  1. 为什么需要项目依赖管理
  2. Python 包、环境、项目到底是什么关系
  3. pip、venv、conda、Poetry、Docker 分别解决什么问题
  4. Poetry 是什么
  5. Poetry 的核心思想
  6. Poetry 安装与基本配置
  7. Poetry 项目结构
  8. pyproject.toml 是什么
  9. TOML 文件基本语法
  10. pyproject.toml 每个区域怎么理解
  11. 哪些配置是 Poetry 默认生成的,哪些是自己写的
  12. pyproject.tomlpoetry.lock 的关系
  13. Poetry 2.x 推荐的新写法
  14. [project].dependencies[tool.poetry.dependencies] 的区别
  15. 版本约束怎么写
  16. 依赖分组:main、dev、test、docs、prod、gpu
  17. package-mode = false 是什么
  18. Poetry 虚拟环境怎么理解
  19. Poetry 和 conda 应该怎么配合
  20. Poetry 能不能安装 torch、CUDA 相关包
  21. 包源配置:清华源、私有源、PyTorch 源
  22. URL wheel 依赖写法
  23. 常用命令完整讲解
  24. 从 0 创建一个 FastAPI 示例项目
  25. 从 0 创建一个图像分类示例项目
  26. Poetry + Docker 的基本思路
  27. 常见问题与避坑
  28. 推荐的学习路线
  29. 最终总结

1. 为什么需要项目依赖管理?

我们先不讲 Poetry,先讲一个最基本的问题:

为什么 Python 项目需要"依赖管理"?

假设你写了一个 Python 文件:

python 复制代码
import requests

response = requests.get("https://example.com")
print(response.status_code)

这个代码依赖了一个第三方库:

text 复制代码
requests

如果你的电脑上没有安装它,运行就会报错:

text 复制代码
ModuleNotFoundError: No module named 'requests'

于是你会安装:

bash 复制代码
pip install requests

这时问题来了:

text 复制代码
你自己电脑装了 requests,别人电脑不一定装了。
你今天装的是 requests 2.32,别人明天装的可能是 requests 2.35。
你项目依赖 requests,但 requests 自己又依赖 urllib3、certifi、idna。
时间一长,你根本不知道环境里哪些包是项目需要的,哪些是随手装的。

所以正式项目必须回答几个问题:

text 复制代码
1. 这个项目需要哪些第三方包?
2. 每个包需要什么版本?
3. 别人如何安装出一样的环境?
4. 部署服务器如何复现本地环境?
5. 如果依赖冲突,怎么提前发现?

这就是依赖管理要解决的问题。


2. Python 包、环境、项目到底是什么关系?

小白最容易混的三个概念是:

text 复制代码
Python 包
Python 环境
Python 项目

我们先拆开。


2.1 Python 包是什么?

Python 包就是别人写好的代码库。

例如:

text 复制代码
fastapi
requests
numpy
opencv-python
torch
pandas
pytest

你可以通过安装包来使用别人写好的功能。

例如:

bash 复制代码
pip install requests

然后代码里:

python 复制代码
import requests

2.2 Python 环境是什么?

Python 环境可以理解为:

一套独立的 Python 解释器 + 第三方包集合。

比如你电脑上可以有多个环境:

text 复制代码
环境 A:
Python 3.8
numpy 1.23
torch 1.13

环境 B:
Python 3.11
numpy 1.26
torch 2.4

环境 C:
Python 3.10
fastapi
uvicorn
sqlalchemy

环境的意义是隔离。

否则所有项目都往同一个 Python 里安装包,就会越来越乱。


2.3 Python 项目是什么?

Python 项目是你写的一套代码,例如:

text 复制代码
blog-api/
├── app/
│   ├── main.py
│   └── routers.py
├── tests/
├── pyproject.toml
└── poetry.lock

项目需要依赖环境运行。

你可以这样理解:

text 复制代码
项目 = 你的代码
环境 = 运行代码的房间
包 = 房间里安装的工具
Poetry = 管理这个项目需要哪些工具的清单系统

3. pip、venv、conda、Poetry、Docker 分别解决什么问题?

这几个工具经常一起出现,很容易乱。

我们用一个表先看整体关系。

工具 它主要解决什么问题 类比
pip 安装 Python 包 买一个工具
venv 创建 Python 虚拟环境 创建一个小房间
conda 创建环境 + 管理 Python/科学计算/部分底层库 创建带装修的大房间
Poetry 管理某个项目的依赖、锁版本、打包 项目的采购清单和合同
Docker 打包整个系统环境 把整套房子装进集装箱

3.1 pip

pip 是 Python 最基础的包安装工具。

bash 复制代码
pip install fastapi

优点:

text 复制代码
简单
直接
几乎所有 Python 用户都会用

缺点:

text 复制代码
不擅长管理完整项目
不擅长锁定版本关系
环境久了容易乱

3.2 venv

venv 是 Python 自带的虚拟环境工具。

bash 复制代码
python -m venv .venv

它可以给项目创建一个独立环境。

优点:

text 复制代码
轻量
官方自带
不用额外安装

缺点:

text 复制代码
只负责创建环境
不负责复杂依赖解析
不负责锁定依赖

3.3 conda

conda 也是环境管理工具,但它更强大,尤其适合科学计算和机器学习。

例如:

bash 复制代码
conda create -n ml python=3.11
conda activate ml

它不仅能装 Python 包,有时还能管理一些非 Python 的二进制依赖。

适合:

text 复制代码
机器学习
深度学习
科学计算
GPU 环境
复杂 C/C++ 库

3.4 Poetry

Poetry 是项目依赖管理工具。

它关心的是:

text 复制代码
这个项目需要哪些包?
版本应该怎么约束?
安装时如何解析依赖?
如何生成锁文件?
如何保证别人安装出来一样?

例如:

bash 复制代码
poetry add fastapi uvicorn
poetry install
poetry run uvicorn app.main:app --reload

3.5 Docker

Docker 管的是整个系统级运行环境。

它可以把这些东西都打包:

text 复制代码
操作系统
Python
系统依赖
Python 包
项目代码
启动命令

正式部署常见组合:

text 复制代码
Docker + Poetry

4. Poetry 是什么?

一句话:

Poetry 是 Python 项目的依赖管理、虚拟环境管理、版本锁定和打包工具。

它主要解决:

text 复制代码
项目依赖声明
项目依赖安装
项目依赖版本锁定
虚拟环境管理
包构建和发布

最核心的两个文件是:

text 复制代码
pyproject.toml
poetry.lock

你可以这样理解:

text 复制代码
pyproject.toml = 人写的项目需求说明
poetry.lock    = Poetry 算出来的精确安装清单

5. Poetry 的核心思想

Poetry 的核心思想不是"装包",而是:

把一个项目的依赖变成清楚、稳定、可复现的配置。

传统做法:

bash 复制代码
pip install fastapi
pip install uvicorn
pip install numpy
pip freeze > requirements.txt

这种方式的问题是:

text 复制代码
requirements.txt 里会混入所有直接依赖和间接依赖
很难看出哪些是你主动安装的
版本关系不够清楚
多人协作容易不一致

Poetry 的做法:

bash 复制代码
poetry add fastapi uvicorn numpy

然后:

text 复制代码
pyproject.toml 记录你主动需要的依赖
poetry.lock 记录解析后的所有精确版本

例如你主动安装:

text 复制代码
fastapi

Poetry 可能会在锁文件中记录:

text 复制代码
fastapi
starlette
pydantic
typing-extensions
anyio

因为这些是 FastAPI 的间接依赖。


6. Poetry 安装与基本配置

6.1 安装 Poetry

推荐使用 pipx 安装 Poetry,因为 Poetry 本身也是 Python 程序,不建议把它安装进某个项目环境里。

bash 复制代码
pipx install poetry

如果没有 pipx,也可以用官方安装脚本。

安装后检查:

bash 复制代码
poetry --version

6.2 推荐配置:让虚拟环境放在项目目录

执行一次:

bash 复制代码
poetry config virtualenvs.in-project true

这样每个项目会生成:

text 复制代码
project/
├── .venv/
├── pyproject.toml
└── poetry.lock

优点:

text 复制代码
环境在哪里一眼能看到
删除项目时环境也一起删除
不容易和其他项目混在一起

7. Poetry 项目结构

执行:

bash 复制代码
poetry new blog-api

可能得到:

text 复制代码
blog-api/
├── README.md
├── pyproject.toml
├── src/
│   └── blog_api/
│       └── __init__.py
└── tests/
    └── __init__.py

如果你已经有项目了,比如:

text 复制代码
blog-api/
├── app/
│   └── main.py
└── tests/

可以进入目录后执行:

bash 复制代码
poetry init

它会帮你生成 pyproject.toml


8. pyproject.toml 是什么?

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

它可以写:

text 复制代码
项目名称
项目版本
作者信息
Python 版本要求
运行依赖
开发依赖
构建系统
包源
工具配置

比如:

toml 复制代码
[project]
name = "blog-api"
version = "0.1.0"
description = "A simple blog API"
requires-python = ">=3.11,<3.12"
dependencies = [
    "fastapi==0.115.0",
    "uvicorn==0.30.6",
]

9. TOML 文件基本语法

pyproject.toml 使用 TOML 格式。

你只需要先掌握四种写法。


9.1 字符串

toml 复制代码
name = "blog-api"

9.2 数组

toml 复制代码
dependencies = [
    "fastapi==0.115.0",
    "uvicorn==0.30.6",
]

9.3 表

toml 复制代码
[project]
name = "blog-api"

[project] 表示下面的内容属于 project 这个区域。


9.4 嵌套表

toml 复制代码
[tool.poetry]
package-mode = false

表示:

text 复制代码
tool 下面的 poetry 区域

10. pyproject.toml 每个区域怎么理解?

常见区域如下:

toml 复制代码
[project]
...

[tool.poetry]
...

[tool.poetry.group.dev.dependencies]
...

[[tool.poetry.source]]
...

[build-system]
...

10.1 [project]

这是项目基本信息区域。

例如:

toml 复制代码
[project]
name = "blog-api"
version = "0.1.0"
description = "A simple blog API"
readme = "README.md"
requires-python = ">=3.11,<3.12"
dependencies = [
    "fastapi==0.115.0",
]

可以理解成:

text 复制代码
项目身份证 + 主依赖列表

10.2 [tool.poetry]

这是 Poetry 自己的配置区域。

例如:

toml 复制代码
[tool.poetry]
package-mode = false

意思是:

text 复制代码
这个项目不是为了打包发布成 Python 库,而是一个应用项目。

10.3 [tool.poetry.group.dev.dependencies]

这是开发依赖组。

toml 复制代码
[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"
ruff = "^0.11.0"
black = "^24.0.0"

意思是:

text 复制代码
这些包开发时需要,项目运行时不一定需要。

10.4 [[tool.poetry.source]]

这是包源配置。

toml 复制代码
[[tool.poetry.source]]
name = "tsinghua"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
priority = "primary"

意思是:

text 复制代码
安装包时使用清华 PyPI 镜像源。

10.5 [build-system]

这是构建系统配置。

toml 复制代码
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

普通使用时一般不用改。


11. 哪些配置是 Poetry 默认生成的,哪些是自己写的?

11.1 Poetry 默认生成的骨架

执行:

bash 复制代码
poetry init

可能生成:

toml 复制代码
[project]
name = "blog-api"
version = "0.1.0"
description = ""
authors = [
    {name = "Your Name", email = "you@example.com"}
]
readme = "README.md"
requires-python = ">=3.11"
dependencies = []

[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

默认生成的通常有:

text 复制代码
[project]
name
version
description
authors
readme
requires-python
dependencies

[build-system]
requires
build-backend

11.2 你通常要自己改的

项目名

toml 复制代码
name = "blog-api"

版本号

toml 复制代码
version = "0.1.0"

描述

toml 复制代码
description = "A simple blog API"

Python 版本范围

toml 复制代码
requires-python = ">=3.11,<3.12"

建议不要写得太宽。比如图像、深度学习、科学计算项目,经常需要限制 Python 版本。


11.3 通常用命令自动添加的

主依赖:

bash 复制代码
poetry add fastapi uvicorn

开发依赖:

bash 复制代码
poetry add pytest ruff black --group dev

Poetry 会自动修改 pyproject.toml


11.4 通常你手动添加的

toml 复制代码
[tool.poetry]
package-mode = false

[tool.ruff]
line-length = 100

[tool.pytest.ini_options]
testpaths = ["tests"]

这些属于项目规范,通常需要自己定。


11.5 基本不要手动改的

toml 复制代码
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

还有:

text 复制代码
poetry.lock

poetry.lock 是 Poetry 自动生成的,不要手写。


12. pyproject.tomlpoetry.lock 的关系

这是超级重要的概念。

text 复制代码
pyproject.toml = 项目需求
poetry.lock    = 最终精确安装结果

举例:

toml 复制代码
[project]
dependencies = [
    "fastapi>=0.115,<1.0",
]

这句话只是说:

text 复制代码
我需要 FastAPI,版本在 0.115 到 1.0 之间。

Poetry 解析后会在 poetry.lock 里锁定具体版本:

text 复制代码
fastapi 0.115.0
starlette 0.xx
pydantic 2.xx
anyio x.xx

正式项目中:

text 复制代码
pyproject.toml 要提交 git
poetry.lock 也要提交 git

13. Poetry 2.x 推荐的新写法

Poetry 2.x 更推荐把主依赖写在:

toml 复制代码
[project]
dependencies = [...]

例如:

toml 复制代码
[project]
name = "blog-api"
version = "0.1.0"
requires-python = ">=3.11,<3.12"
dependencies = [
    "fastapi==0.115.0",
    "uvicorn==0.30.6",
]

这是现代 Python 项目的标准写法。


14. [project].dependencies[tool.poetry.dependencies] 的区别

很多教程会写:

toml 复制代码
[tool.poetry.dependencies]
python = ">=3.11,<3.12"
fastapi = "0.115.0"
uvicorn = "0.30.6"

这是老式 Poetry 写法。

而现代推荐:

toml 复制代码
[project]
requires-python = ">=3.11,<3.12"
dependencies = [
    "fastapi==0.115.0",
    "uvicorn==0.30.6",
]

14.1 它们是不是一样?

不完全一样。

写法 定位 特点
[project].dependencies Python 标准项目元数据 推荐主依赖使用
[tool.poetry.dependencies] Poetry 专属配置 老写法,也可表达 Poetry 特有信息
[tool.poetry.group.xxx.dependencies] Poetry 依赖组 用于 dev/test/docs/gpu 等分组

普通包用二者表达相似:

toml 复制代码
[project]
dependencies = [
    "fastapi==0.115.0",
]

和:

toml 复制代码
[tool.poetry.dependencies]
fastapi = "0.115.0"

都表示需要 FastAPI 0.115.0。

但更推荐新写法。


14.2 什么时候还会用 [tool.poetry.dependencies]

当你需要 Poetry 特有能力时,例如:

text 复制代码
指定 source
某些复杂依赖锁定信息
一些旧项目兼容

如果你完全使用旧写法,建议在 [project] 中加:

toml 复制代码
dynamic = ["dependencies"]

表示:

text 复制代码
依赖不直接写在 [project].dependencies,而是由工具动态提供。

15. 版本约束怎么写?

依赖版本约束是 Poetry 的核心之一。

15.1 精确版本

toml 复制代码
dependencies = [
    "fastapi==0.115.0",
]

意思是:

text 复制代码
只能安装 fastapi 0.115.0

优点:

text 复制代码
最稳定

缺点:

text 复制代码
升级不灵活
依赖冲突时不好调整

15.2 范围版本

toml 复制代码
dependencies = [
    "fastapi>=0.115,<1.0",
]

意思是:

text 复制代码
可以安装 >=0.115 且 <1.0 的版本

15.3 Poetry 的 ^ 写法

在 Poetry 专属区域常见:

toml 复制代码
[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"

大致等价于:

text 复制代码
>=8.0.0,<9.0.0

15.4 *

toml 复制代码
some-package = "*"

意思是:

text 复制代码
任何版本都可以

正式项目中不太推荐,因为太宽。


15.5 小白推荐规则

对于普通服务项目:

toml 复制代码
dependencies = [
    "fastapi>=0.115,<1.0",
    "uvicorn>=0.30,<1.0",
]

对于容易出问题的底层包:

toml 复制代码
dependencies = [
    "numpy>=1.26,<2.0",
]

对于你必须固定的特殊包:

toml 复制代码
dependencies = [
    "some-special-package==1.2.3",
]

16. 依赖分组:main、dev、test、docs、prod、gpu

依赖不是都应该放在一起。

我们先分清:

text 复制代码
运行时依赖:项目启动必须要
开发依赖:开发时才需要
测试依赖:跑测试才需要
文档依赖:生成文档才需要
平台依赖:某些硬件/GPU/系统才需要

16.1 main 主依赖

主依赖写在:

toml 复制代码
[project]
dependencies = [
    "fastapi==0.115.0",
    "uvicorn==0.30.6",
]

这些默认会安装。


16.2 dev 开发依赖

toml 复制代码
[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"
ruff = "^0.11.0"
black = "^24.0.0"

安装时默认会安装非 optional 的依赖组。

如果不想装 dev:

bash 复制代码
poetry install --without dev

16.3 optional 可选依赖组

例如 GPU 环境才需要:

toml 复制代码
[tool.poetry.group.gpu]
optional = true

[tool.poetry.group.gpu.dependencies]
torch = "^2.4.0"
torchvision = "^0.19.0"

默认安装:

bash 复制代码
poetry install

不会安装 optional 的 gpu 组。

需要时:

bash 复制代码
poetry install --with gpu

16.4 分组原则

放主依赖:

text 复制代码
项目运行一定需要

放 dev:

text 复制代码
只开发时需要

放 test:

text 复制代码
只测试时需要

放 docs:

text 复制代码
只写文档时需要

放 gpu/cpu/platform:

text 复制代码
只有特定平台才需要

17. package-mode = false 是什么?

Poetry 默认会把项目当成一个"可以打包发布的 Python 包"。

比如你创建一个库:

text 复制代码
math-tools/
├── src/
│   └── math_tools/
│       └── __init__.py
└── pyproject.toml

这种项目可以发布到 PyPI,让别人:

bash 复制代码
pip install math-tools

但很多项目不是库,而是应用,例如:

text 复制代码
blog-api/
├── app/
│   └── main.py
└── pyproject.toml

这种只是一个服务,不一定要发布成 Python 包。

这时建议:

toml 复制代码
[tool.poetry]
package-mode = false

意思是:

text 复制代码
这个项目只是应用,不按包项目处理。

适合:

text 复制代码
FastAPI 服务
脚本项目
内部工具
数据处理项目
不准备发布到 PyPI 的应用

18. Poetry 虚拟环境怎么理解?

Poetry 默认会给项目创建虚拟环境。

你可以查看:

bash 复制代码
poetry env info --path

如果设置了:

bash 复制代码
poetry config virtualenvs.in-project true

那么环境就在:

text 复制代码
project/.venv/

运行命令时:

bash 复制代码
poetry run python main.py

意思是:

text 复制代码
使用 Poetry 为当前项目管理的虚拟环境里的 Python 来运行 main.py

不要直接裸跑:

bash 复制代码
python main.py

因为你可能用的是系统 Python 或其他环境的 Python。


19. Poetry 和 conda 应该怎么配合?

19.1 原则

text 复制代码
conda 管环境
Poetry 管项目依赖

19.2 推荐方式 A:只用 Poetry 的 .venv

适合普通项目:

bash 复制代码
cd blog-api
poetry config virtualenvs.in-project true
poetry install

19.3 推荐方式 B:一个项目一个 conda 环境 + Poetry

适合复杂科学计算或特殊平台项目:

bash 复制代码
conda create -n image-classifier-py311 python=3.11
conda activate image-classifier-py311

cd image-classifier
poetry config virtualenvs.create false --local
poetry install

注意:

一个 conda 环境只给一个正式项目用。

不要:

text 复制代码
一个 conda 环境装十几个正式项目依赖

19.4 不推荐的方式

bash 复制代码
conda activate base
poetry install

不推荐在 base 环境里做项目。


20. Poetry 能不能安装 torch、CUDA 相关包?

结论:

text 复制代码
Poetry 可以安装 torch 这种 Python 包
Poetry 可以安装 CUDA 版 torch wheel
Poetry 不能安装 NVIDIA 显卡驱动
Poetry 一般不负责系统级 CUDA Toolkit

理解 CUDA 要分层:

text 复制代码
第 1 层:显卡驱动
第 2 层:系统 CUDA Toolkit / nvcc / cuDNN
第 3 层:PyTorch wheel 自带或依赖的 CUDA runtime
第 4 层:torch Python 包

Poetry 负责第 4 层,以及一部分第 3 层的 Python wheel。

验证:

bash 复制代码
poetry run python -c "import torch; print(torch.cuda.is_available()); print(torch.version.cuda)"

21. 包源配置:清华源、私有源、PyTorch 源

21.1 清华源

toml 复制代码
[[tool.poetry.source]]
name = "tsinghua"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
priority = "primary"

含义:

text 复制代码
普通依赖优先从清华源下载。

21.2 PyTorch CUDA 源

使用命令添加:

bash 复制代码
poetry source add --priority=explicit pytorch-cu118 https://download.pytorch.org/whl/cu118
poetry add --source pytorch-cu118 torch torchvision torchaudio

explicit 的意思是:

text 复制代码
只有明确指定这个源的包才从这里下载。

这样比较安全。


22. URL wheel 依赖写法

有些包不是从 PyPI 安装,而是直接给一个 wheel 链接。

22.1 新标准写法

toml 复制代码
[project]
dependencies = [
    "my-runtime @ https://example.com/packages/my_runtime-1.0.0-cp311-cp311-manylinux_x86_64.whl",
]

22.2 Poetry 专属写法

toml 复制代码
[tool.poetry.dependencies]
my-runtime = { url = "https://example.com/packages/my_runtime-1.0.0-cp311-cp311-manylinux_x86_64.whl" }

22.3 wheel 文件名怎么读?

例如:

text 复制代码
my_runtime-1.0.0-cp311-cp311-manylinux_x86_64.whl

可以拆成:

text 复制代码
my_runtime  包名
1.0.0       版本
cp311       CPython 3.11
manylinux   Linux 平台
x86_64      CPU 架构

如果 wheel 是 cp311,Python 版本就应该是 3.11。

建议:

toml 复制代码
requires-python = ">=3.11,<3.12"

23. 常用命令完整讲解

23.1 初始化项目

已有项目:

bash 复制代码
poetry init

新建项目:

bash 复制代码
poetry new blog-api

23.2 安装依赖

bash 复制代码
poetry install

根据 pyproject.tomlpoetry.lock 安装。

更严格:

bash 复制代码
poetry sync

sync 会让环境和锁文件同步,并移除多余包。


23.3 添加依赖

bash 复制代码
poetry add fastapi uvicorn

添加到 dev 组:

bash 复制代码
poetry add pytest ruff black --group dev

23.4 删除依赖

bash 复制代码
poetry remove fastapi

删除 dev 组依赖:

bash 复制代码
poetry remove pytest --group dev

23.5 运行命令

bash 复制代码
poetry run python main.py

运行 FastAPI:

bash 复制代码
poetry run uvicorn app.main:app --reload

运行测试:

bash 复制代码
poetry run pytest

23.6 查看依赖

bash 复制代码
poetry show

查看依赖树:

bash 复制代码
poetry show --tree

查看过期:

bash 复制代码
poetry show --outdated

23.7 更新依赖

更新全部:

bash 复制代码
poetry update

更新指定包:

bash 复制代码
poetry update fastapi

只更新 lock:

bash 复制代码
poetry lock

23.8 检查配置

bash 复制代码
poetry check

23.9 查看环境

bash 复制代码
poetry env info
poetry env info --path

指定 Python:

bash 复制代码
poetry env use python3.11

24. 从 0 创建一个 FastAPI 示例项目

项目名:

text 复制代码
blog-api

24.1 创建项目目录

bash 复制代码
mkdir blog-api
cd blog-api
poetry init

一路按提示填写,也可以先默认。


24.2 配置虚拟环境在项目目录

bash 复制代码
poetry config virtualenvs.in-project true

24.3 添加依赖

bash 复制代码
poetry add fastapi uvicorn
poetry add pytest ruff black --group dev

24.4 创建代码

text 复制代码
blog-api/
├── app/
│   └── main.py
├── tests/
├── pyproject.toml
└── poetry.lock

app/main.py

python 复制代码
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def root():
    return {"message": "hello blog api"}

24.5 运行

bash 复制代码
poetry run uvicorn app.main:app --reload

浏览器访问:

text 复制代码
http://127.0.0.1:8000

24.6 推荐配置

toml 复制代码
[project]
name = "blog-api"
version = "0.1.0"
description = "A simple blog API"
readme = "README.md"
requires-python = ">=3.11,<3.12"
dependencies = [
    "fastapi>=0.115,<1.0",
    "uvicorn>=0.30,<1.0",
]

[tool.poetry]
package-mode = false

[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"
ruff = "^0.11.0"
black = "^24.0.0"

[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

25. 从 0 创建一个图像分类示例项目

项目名:

text 复制代码
image-classifier

25.1 创建项目

bash 复制代码
mkdir image-classifier
cd image-classifier
poetry init

25.2 添加依赖

bash 复制代码
poetry add numpy opencv-python pillow
poetry add pytest ruff black --group dev

如果你需要 PyTorch CPU/GPU,可以按实际情况添加。

普通:

bash 复制代码
poetry add torch torchvision

特定 PyTorch 源:

bash 复制代码
poetry source add --priority=explicit pytorch-cu118 https://download.pytorch.org/whl/cu118
poetry add --source pytorch-cu118 torch torchvision

25.3 示例结构

text 复制代码
image-classifier/
├── src/
│   └── classifier/
│       ├── __init__.py
│       └── predict.py
├── tests/
├── pyproject.toml
└── poetry.lock

25.4 推荐配置

toml 复制代码
[project]
name = "image-classifier"
version = "0.1.0"
description = "A simple image classification demo"
readme = "README.md"
requires-python = ">=3.11,<3.12"
dependencies = [
    "numpy>=1.26,<2.0",
    "opencv-python>=4.9,<5.0",
    "pillow>=10,<12",
]

[tool.poetry]
package-mode = false

[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"
ruff = "^0.11.0"
black = "^24.0.0"

[tool.poetry.group.gpu]
optional = true

[tool.poetry.group.gpu.dependencies]
torch = "^2.4.0"
torchvision = "^0.19.0"

[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

普通安装:

bash 复制代码
poetry install

带 GPU 组:

bash 复制代码
poetry install --with gpu

26. Poetry + Docker 的基本思路

Docker 部署中常见思路:

text 复制代码
Docker 提供系统环境
Poetry 安装 Python 依赖

示例:

dockerfile 复制代码
FROM python:3.11-slim

WORKDIR /app

RUN pip install poetry

COPY pyproject.toml poetry.lock ./

RUN poetry config virtualenvs.create false \
    && poetry install --only main --no-root

COPY . .

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

注意:

text 复制代码
容器本身已经隔离,所以 Docker 里经常关闭 Poetry 虚拟环境。

但前提是你知道自己在做什么,基础镜像要干净。


27. 常见问题与避坑

27.1 不要在 base 环境里做项目

不推荐:

bash 复制代码
conda activate base
poetry install

推荐:

bash 复制代码
conda create -n blog-api-py311 python=3.11
conda activate blog-api-py311

27.2 不要多个正式项目共用一个 conda 环境

正式项目建议:

text 复制代码
一个项目一个环境

临时实验可以共用一个环境。


27.3 不要乱混 pip、conda、Poetry

最容易乱:

bash 复制代码
conda install numpy
pip install numpy==2.0
poetry add numpy

建议:

text 复制代码
先明确谁是这个项目的主要依赖管理工具。

27.4 requires-python 不要写太宽

如果项目依赖很多底层库,建议:

toml 复制代码
requires-python = ">=3.11,<3.12"

不要随便写:

toml 复制代码
requires-python = ">=3.11"

27.5 不要乱用 *

不推荐:

toml 复制代码
some-package = "*"

更推荐:

toml 复制代码
dependencies = [
    "some-package>=1.2,<2.0",
]

27.6 服务项目建议 package-mode = false

如果不是要发布到 PyPI:

toml 复制代码
[tool.poetry]
package-mode = false

27.7 poetry.lock 不要手改

如果依赖有问题,通过命令处理:

bash 复制代码
poetry add
poetry remove
poetry update
poetry lock
poetry sync

27.8 poetry installpoetry update 不要混淆

text 复制代码
poetry install = 按已有 lock 安装
poetry update  = 更新依赖版本并刷新 lock

克隆项目后,优先:

bash 复制代码
poetry install

不要上来就:

bash 复制代码
poetry update

27.9 poetry sync 更适合保持环境干净

bash 复制代码
poetry sync

它会删除环境里不属于当前锁文件的包。


28. 推荐的学习路线

阶段 1:先会用

掌握:

bash 复制代码
poetry init
poetry add
poetry install
poetry run
poetry remove

目标:

text 复制代码
能创建项目、添加依赖、运行代码。

阶段 2:理解文件

掌握:

text 复制代码
pyproject.toml
poetry.lock
[project]
dependencies
requires-python
[build-system]

目标:

text 复制代码
看懂项目为什么能安装,为什么能复现。

阶段 3:理解环境

掌握:

text 复制代码
.venv
poetry env info
conda + Poetry
poetry config virtualenvs.in-project true
poetry config virtualenvs.create false --local

目标:

text 复制代码
知道代码到底在哪个 Python 环境中运行。

阶段 4:理解工程实践

掌握:

text 复制代码
dev/test/docs/gpu 分组
package-mode = false
包源配置
URL wheel
Docker + Poetry

目标:

text 复制代码
能管理正式 Python 项目。

29. 最终总结

你可以把整个体系记成这几句话:

text 复制代码
pip 是安装包的工具。
venv 是创建虚拟环境的工具。
conda 是更强的环境管理工具,适合科学计算和 GPU 场景。
Poetry 是项目级依赖管理工具。
Docker 是系统级打包部署工具。

pyproject.toml 是:

text 复制代码
项目总配置文件

poetry.lock 是:

text 复制代码
精确版本锁定文件

现代 Poetry 项目推荐:

toml 复制代码
[project]
name = "demo"
version = "0.1.0"
requires-python = ">=3.11,<3.12"
dependencies = [
    "fastapi>=0.115,<1.0",
]

[tool.poetry]
package-mode = false

[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"

[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

小白最应该先掌握的不是所有高级配置,而是这条主线:

text 复制代码
创建项目
→ 添加依赖
→ 生成 lock
→ 使用 poetry run 运行
→ 理解 pyproject.toml
→ 理解 poetry.lock
→ 理解环境隔离

只要这条线通了,Poetry 就不再是一个"看起来很复杂的工具",而是你管理 Python 项目的好帮手。