近期在项目中遇到一些特殊情况,uv 无法满足需求,调研发现 Poetry 能够较好解决,因此决定在该项目中改用 Poetry 进行管理。为方便日常使用,特将常用命令与配置整理为学习笔记。
注:之前一直用uv是因为启动缓存后,uv安装依赖比较快,并且用着也挺方便。
1. Poetry 简述
1.1 Python 包管理的痛点
传统的 Python 项目依赖管理面临这些问题:
# 混乱的依赖管理pip install package1pip install package2==1.3.0# 几周后...pip install package3# 项目突然崩溃了!不知道哪个包冲突了# 虚拟环境管理困难python -m venv .venv# Windows.venv\Scripts\activate# Linux/Macsource .venv/bin/activate# 每次都忘记激活
1.2 Poetry 的解决方案
Poetry 解决了这些核心问题:
- 确定性的构建:
poetry.lock 确保每次安装相同的版本 - 现代标准:支持 PEP 621、pyproject.toml 标准
1.3 Poetry vs uv
| | | |
|---|
| 依赖管理 | | | |
| 虚拟环境 | | | |
| 发布 PyPI | | | Poetry 优势 |
| 私有仓库 | | | Poetry 优势 |
| 插件系统 | | | Poetry 优势 |
| 构建打包 | | | |
| 性能速度 | | | |
2. 安装与配置
2.1 安装 Poetry
Windows (PowerShell)
# 官方推荐方式(使用 pipx)# 1. 先安装 pipxpython -m pip install --user pipxpython -m pipx ensurepath# 2. 用 pipx 安装 Poetrypipx install poetry# 验证安装poetry --version
macOS/Linux
# 使用官方安装脚本curl -sSL https://install.python-poetry.org | python3 -# 或使用 pippip install --user poetry# 验证安装poetry --version
2.2 配置国内镜像(加速下载)
# 查看当前配置poetry config --list# 配置清华源poetry source add tsinghua https://pypi.tuna.tsinghua.edu.cn/simple/ --priority="primary"# 配置阿里云作为备用源poetry source add aliyun https://mirrors.aliyun.com/pypi/simple/ --priority="supplemental"# 验证源配置poetry source list
3. 创建一个 Poetry 项目
3.1 从零创建项目
# 创建一个新项目poetry new my-awesome-project# 查看生成的项目结构cd my-awesome-projecttree .
生成的项目结构:
my-awesome-project/├── pyproject.toml # 项目配置文件├── README.md # 项目说明文档├── my_awesome_project/ # 源码目录│ └── __init__.py└── tests/ # 测试目录 └── __init__.py
3.2 理解 pyproject.toml
让我们看看自动生成的 pyproject.toml:
# 项目元数据(PEP 621 标准格式)[project]name = "my-awesome-project"version = "0.1.0"description = ""authors = [ {name = "Your Name", email = "you@example.com"}]license = {text = ""}readme = "README.md"requires-python = ">=3.8"# 依赖声明dependencies = []# 可选依赖(开发依赖)[project.optional-dependencies]dev = []# 构建系统配置[build-system]requires = ["poetry-core>=2.0.0,<3.0.0"]build-backend = "poetry.core.masonry.api"
3.3 创建项目并指定参数
# 创建时指定更多参数poetry new ai-chatbot \ --name "ai-chatbot" \ --python "^3.13" \ --dependency "playwright@^1.48.0" \ --dependency "fastapi@^0.115.0" \ --author "码上工坊 <3892493481@qq.com>" \ --license "MIT" \ --readme "README.md"# 或交互式创建poetry new --interactive
4. 依赖管理实战
4.1 添加依赖
# 添加生产依赖poetry add requests # 添加最新版本poetry add "requests>=2.31.0"# 指定最小版本poetry add "requests@^2.31.0"# 兼容版本(2.31.0 <= version < 3.0.0)# 添加开发依赖poetry add --group dev pytestpoetry add --group dev black isort flake8# 添加可选依赖组poetry add --group docs sphinxpoetry add --group test pytest pytest-covpoetry add --group lint black flake8 mypy
4.2 理解版本约束
Poetry 支持多种版本约束语法:
dependencies = [ # 精确版本 "requests==2.31.0", # 兼容版本(最常用) "requests>=2.31.0,<3.0.0", # 传统写法 "requests@^2.31.0", # 简写,等价于上面 # 波浪符约束 "requests~=2.31.0", # 2.31.0 <= version < 2.32.0 # 通配符 "requests==2.*", # 2.x 的任何版本 # 不等式 "requests>2.30", # 大于 2.30 "requests<=3.0", # 小于等于 3.0 # 多条件 "requests>=2.0,!=2.5.*,<3.0",]
4.3 移除和更新依赖
# 移除依赖poetry remove requestspoetry remove --group dev pytest# 更新依赖poetry update # 更新所有依赖到最新兼容版本poetry update requests # 只更新 requestspoetry update --lock # 只更新 lock 文件,不安装# 查看过时的依赖poetry show --outdated# 查看依赖树poetry show --tree
5. 虚拟环境管理
5.1 理解虚拟环境
# 创建虚拟环境并安装依赖poetry install# 如果只想安装生产依赖(不安装开发依赖)poetry install --only main# 如果只想安装开发依赖poetry install --only dev# 激活虚拟环境poetry shell# 在虚拟环境中运行命令(不激活)poetry run python script.pypoetry run pytestpoetry run black .# 查看虚拟环境信息poetry env info
5.2 虚拟环境配置选项
# 配置虚拟环境在项目目录内(推荐)poetry config virtualenvs.in-project true# 查看当前虚拟环境poetry env list# 指定 Python 版本poetry env use python3.13poetry env use /usr/bin/python3.13# 删除虚拟环境poetry env remove python3.13# 查看虚拟环境路径poetry env info --path
5.3 跨平台项目配置
# 在 pyproject.toml 中配置平台特定依赖[tool.poetry.group.dev.dependencies]# 所有平台都需要的开发工具pytest = "^8.0.0"black = "^24.0.0"# 平台特定依赖[tool.poetry.group.dev.dependencies.windows]pywin32 = {version = ">=306", markers = "sys_platform == 'win32'"}[tool.poetry.group.dev.dependencies.linux]# Linux 特定工具# Python 版本特定依赖typing-extensions = {version = "^4.8.0", markers = "python_version < '3.11'"}
6. 项目开发和构建
6.1 项目结构最佳实践
my-project/├── pyproject.toml # 项目配置├── README.md # 项目说明├── CHANGELOG.md # 版本变更记录├── LICENSE # 许可证├── .gitignore # Git 忽略文件├── .python-version # Python 版本(可选)├── src/ # 源码目录(推荐结构)│ └── my_package/│ ├── __init__.py│ ├── core.py│ └── utils.py├── tests/ # 测试目录│ ├── __init__.py│ ├── test_core.py│ └── test_utils.py├── docs/ # 文档目录│ └── index.md├── examples/ # 示例代码│ └── basic_usage.py└── scripts/ # 脚本目录 └── setup.py
6.2 添加脚本和入口点
# 在 pyproject.toml 中添加脚本[project.scripts]# 直接指向函数my-cli = "my_package.cli:main"# 指向模块my-tool = "my_package.tools:cli"# 控制台脚本[project.gui-scripts]my-gui = "my_package.gui:main"# 使用 tool.poetry.scripts(传统方式)[tool.poetry.scripts]start-server = "my_package.server:start"
6.3 构建和发布
# 构建项目poetry build# 生成 dist/ 目录包含:# - my-project-0.1.0.tar.gz# - my_project-0.1.0-py3-none-any.whl# 发布到 PyPI# 1. 配置 PyPI tokenpoetry config pypi-token.pypi your-token-here# 2. 发布poetry publish# 发布到测试 PyPIpoetry publish --repository testpypi# 只验证,不上传poetry publish --dry-run
7. 其他特性
7.1 依赖组管理
# 创建自定义依赖组poetry add --group docs sphinx sphinx-rtd-themepoetry add --group test pytest pytest-cov pytest-mockpoetry add --group dev black isort flake8 mypy pre-commit# 安装特定组的依赖poetry install --with docs,test# 排除特定组的依赖poetry install --without dev# 查看所有依赖组poetry show --groups
7.2 私有的包仓库
# 添加私有仓库poetry source add company-private https://pypi.company.com/simple/ --priority="supplemental"# 发布到私有仓库poetry publish --repository company-private# 从私有仓库安装poetry add --source company-private internal-package# 配置认证poetry config http-basic.company-private username password
7.3 插件系统
# 安装 Poetry 插件poetry self add poetry-plugin-export# 使用插件:导出 requirements.txtpoetry export --without-hashes --output requirements.txt# 查看已安装插件poetry self show plugins# 移除插件poetry self remove poetry-plugin-export
8. 实践案例2:AI Webot
让我们用 Poetry 重建我们的 AI Webot 项目:
8.1 项目初始化
# 创建项目poetry new ai-webot --name ai-webot --src# 进入项目cd ai-webot# 配置项目内虚拟环境poetry config virtualenvs.in-project true# 配置国内镜像poetry source add tsinghua https://pypi.tuna.tsinghua.edu.cn/simple/ --priority="primary"
8.2 完整的 pyproject.toml
[project]name = "ai-webot"version = "0.1.0"description = "AI Web版对话机器人框架(基于 Python 和 Playwright 的教育应用项目)"authors = [ {name = "码上工坊", email = "3892493481@qq.com"}]license = {text = "MIT"}readme = "README.md"requires-python = ">=3.13"keywords = ["ai", "chatbot", "automation", "playwright", "python"]classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Education", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3.13",]# 运行时依赖dependencies = [ "playwright>=1.48.0,<2.0.0", "typing-extensions>=4.12.0,<5.0.0", "pydantic>=2.0.0,<3.0.0", "loguru>=0.7.0,<1.0.0",]# 可选依赖组[project.optional-dependencies]dev = [ "pytest>=8.0.0,<9.0.0", "pytest-asyncio>=0.23.0,<1.0.0", "pytest-cov>=5.0.0,<6.0.0", "black>=24.0.0,<25.0.0", "isort>=5.13.0,<6.0.0", "flake8>=7.0.0,<8.0.0", "mypy>=1.9.0,<2.0.0", "pre-commit>=3.6.0,<4.0.0",]test = [ "pytest>=8.0.0,<9.0.0", "pytest-asyncio>=0.23.0,<1.0.0", "pytest-cov>=5.0.0,<6.0.0",]docs = [ "sphinx>=7.0.0,<8.0.0", "sphinx-rtd-theme>=1.3.0,<2.0.0", "myst-parser>=2.0.0,<3.0.0",]# 项目脚本[project.scripts]ai-webot = "ai_webot.main:main"ai-webot-config = "ai_webot.config:cli"# 入口点[project.entry-points."ai_webot.plugins"]deepseek = "ai_webot.bots.deepseek:DeepSeekBot"qianwen = "ai_webot.bots.qianwen:QianWenBot"doubao = "ai_webot.bots.doubao:DouBaoBot"# 构建系统[build-system]requires = ["poetry-core>=2.0.0,<3.0.0"]build-backend = "poetry.core.masonry.api"# Poetry 特定配置[[tool.poetry.source]]name = "tsinghua"url = "https://pypi.tuna.tsinghua.edu.cn/simple/"priority = "primary"# 工具配置[tool.black]line-length = 88target-version = ['py313']include = '\.pyi?$'[tool.isort]profile = "black"line_length = 88[tool.mypy]python_version = "3.13"warn_return_any = truewarn_unused_configs = truedisallow_untyped_defs = true[tool.pytest.ini_options]asyncio_mode = "auto"testpaths = ["tests"]python_files = ["test_*.py"]python_classes = ["Test*"]python_functions = ["test_*"]addopts = "-v --cov=ai_webot --cov-report=term-missing"[tool.coverage.run]source = ["ai_webot"]omit = ["*/tests/*", "*/__pycache__/*"][tool.coverage.report]exclude_lines = [ "pragma: no cover", "def __repr__", "raise AssertionError", "raise NotImplementedError",]
8.3 项目开发和测试
# 1. 安装所有依赖poetry install# 2. 进入开发环境poetry shell# 3. 运行代码质量检查poetry run black . # 代码格式化poetry run isort . # 导入排序poetry run flake8 . # 代码风格检查poetry run mypy . # 类型检查# 4. 运行测试poetry run pytest -v # 运行所有测试poetry run pytest --cov # 运行测试并查看覆盖率# 5. 构建项目poetry build# 6. 发布前检查poetry check # 检查配置poetry publish --dry-run # 模拟发布
9. 团队协作
9.1 Git 工作流集成
# .gitignore 应该包含.venv/ # Poetry 虚拟环境dist/ # 构建产物*.egg-info/ # 包信息__pycache__/ # Python 缓存.pytest_cache/ # Pytest 缓存.coverage # 覆盖率报告# pre-commit 配置 (.pre-commit-config.yaml)repos: - repo: https://github.com/psf/black rev: 24.8.0 hooks: - id: black - repo: https://github.com/PyCQA/isort rev: 5.13.2 hooks: - id: isort - repo: https://github.com/PyCQA/flake8 rev: 7.0.0 hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.9.0 hooks: - id: mypy
9.2 持续集成(CI)配置
# .github/workflows/ci.ymlname:CIon:[push,pull_request]jobs:test:runs-on:ubuntu-lateststrategy:matrix:python-version:["3.11","3.12","3.13"]steps:-uses:actions/checkout@v4-name:SetupPythonuses:actions/setup-python@v4with:python-version:${{matrix.python-version}}-name:InstallPoetryrun:pipxinstallpoetry-name:Installdependenciesrun:poetryinstall--withtest-name:Codequalityrun:| poetry run black --check . poetry run isort --check-only . poetry run flake8 . poetry run mypy .-name:Runtestsrun:poetryrunpytest--cov--cov-report=xml-name:Uploadcoverageuses:codecov/codecov-action@v3with:file:./coverage.xml
10. 常见问题
10.1 常见问题
# 1. 依赖解析失败poetry lock --no-update # 重新解析但不更新poetry update # 更新所有依赖# 2. 虚拟环境问题poetry env remove python # 删除当前虚拟环境poetry install # 重新创建# 3. 缓存问题poetry cache clear pypi # 清理 PyPI 缓存poetry cache clear . # 清理所有缓存# 4. 配置问题poetry config --list # 查看所有配置poetry config --unset virtualenvs.path # 重置配置
10.2 使用技巧
# 1. 生成 requirements.txt(用于其他工具)poetry export --without-hashes --output requirements.txt# 2. 查看依赖的许可证poetry show --license# 3. 安全审计poetry show --no-dev --tree # 查看生产依赖树poetry audit # 检查安全漏洞# 4. 性能优化# 设置并行下载poetry config experimental.new-installer false# 5. 环境变量export POETRY_VIRTUALENVS_IN_PROJECT=trueexport POETRY_HTTP_TIMEOUT=60
11 还可以干什么
11.1 自定义插件开发
# my_poetry_plugin.pyfrom poetry.plugins.application_plugin import ApplicationPluginfrom poetry.console.application import Applicationfrom cleo.commands.command import CommandclassMyCommand(Command): name = "my-command"defhandle(self): self.line("Hello from custom plugin!")classMyPlugin(ApplicationPlugin):defactivate(self, application: Application): application.command_loader.register_factory(MyCommand.name, lambda: MyCommand())
11.2 多项目工作区
# 创建 workspacepoetry new workspace --name workspacecd workspace# 添加子项目poetry workspace add ../project-apoetry workspace add ../project-b# 安装所有项目的依赖poetry install# 在工作区中运行命令poetry run python -c "import project_a; import project_b"
12. 命令速查表
12.1 Poetry 命令速查表
# 项目创建和管理poetry new <name> # 创建新项目poetry init # 交互式初始化poetry install # 安装所有依赖poetry update # 更新依赖# 依赖管理poetry add <package> # 添加依赖poetry remove <package> # 移除依赖poetry show # 显示依赖poetry show --tree # 显示依赖树poetry show --outdated # 显示过时的依赖# 虚拟环境poetry shell # 激活虚拟环境poetry env info # 虚拟环境信息poetry env list # 列出所有环境poetry run <command> # 在虚拟环境中运行命令# 构建和发布poetry build # 构建包poetry publish # 发布到 PyPIpoetry check # 检查配置# 配置poetry config --list # 查看配置poetry source list # 查看源
练习题目参考
练习 1:创建个人工具包
# 创建一个名为 "my-tools" 的工具包# 包含:requests, pandas, click# 添加开发依赖:pytest, black# 添加一个命令行工具# 发布到私有 Git 仓库
练习 2:迁移现有项目
# 将一个使用 requirements.txt 的旧项目迁移到 Poetry# 1. 创建 pyproject.toml# 2. 转换 requirements.txt 为 Poetry 格式# 3. 设置虚拟环境# 4. 配置 CI/CD
练习 3:多环境配置
# 创建一个支持多环境的项目# - 开发环境:所有开发工具# - 测试环境:测试框架# - 生产环境:最小依赖# 配置不同的安装命令