Poetry 是 Python 中用于依赖管理和打包的工具。它最强大的功能是打包与分发,第一次通读peotry官方文档后,给我的感觉是peotry与Pipenv他俩差不多呀,我甚至还感觉peotry不如Pipenv,因为它在进行应用项目的依赖管理的时候,无法像Pipenv那样通过Pyenv自动安装python解释器,而是显性的指定Python解释器。经过一些简单的实践与探索我才体会到peotry的强大,并为自己浅薄的见解感到惭愧。在这里我将对Poetry 安装与基本命令、依赖管理、打包与发布这几个阶段进行实践的简单记录,以便日后复盘。
| 功能 | Poetry | Pipenv | 备注 |
|---|---|---|---|
| 依赖解析 | 新的、快速、确定性 | 老的、可能慢 | Poetry 更可靠 |
| 虚拟环境管理 | 每个项目单独 venv,可手动指定 Python | 自动创建 venv,可集成 Pyenv | Poetry 更显式,Pipenv 更自动 |
| 打包与发布 | 支持完全,使用 pyproject.toml | 支持有限,依赖 setup.py 或 Pipfile | Poetry 对库发布更好 |
| pyproject.toml 支持 | 完全支持 PEP 518/621 | 部分支持 | Poetry 更符合现代标准 |
| Python 解释器安装 | 不会自动安装 | 可通过 Pyenv 自动安装 | Poetry 需要手动指定路径 |
| Lock 文件 | poetry.lock,跨系统可重现 | Pipfile.lock | 两者都可重现环境,但 Poetry 更严格 |
zsh# 安装 Poetry(pipx 或官方推荐方式) pipx install poetry # 回退稳定版本(目前2.XX版本存在一些bug让我吃了点苦头😡) pipx install "poetry==1.8.3" --force # Zsh 启用 Tab 补全功能 poetry completions zsh > ~/.zfunc/_poetry # 查看~/.zshrc配置文件中是否存在一下命令,若没有请添加 fpath+=~/.zfunc autoload -Uz compinit && compinit # 更新 Poetry pipx upgrade poetry # 删除 Poetry pipx uninstall poetry # 创建项目 poetry new my_project poetry init # 也可用现有项目 # 查看虚拟环境列表,注意只有在创建项目的目录下方能生效 poetry env list
zsh# 创建新的初始化项目,名为“poetry-demo” poetry new poetry-demo # 查看目录结构 tree demo-project1 -a # 项目目录结构如下 demo-project1 ├── pyproject.toml ├── README.md ├── src │ └── demo_project1 │ └── __init__.py └── tests └── __init__.py 4 directories, 4 files
踩坑
本人在初始化项目的时候,产生如下报错:
zshpoetry new demo-project Command '['/Users/jingwei/.pyenv/shims/python', '-EsSc', 'import sys; print(sys.executable)']' returned non-zero exit status 127.
情景:
本机系统中python解释器版本为py3.11.1,pyenv安装的py版本为2.7.18、3.9.1、3.10.7。当时在pyenv local命令作用的文件夹中可以使用poetry new命令创建项目,但是当我在此文件夹外进行poetry new命令创建项目时就会调不到system版本。
报错内容分析:
zshexport PATH="$HOME/.pyenv/shims:$PATH"
这意味着:
system,为什么 Poetry 不能直接用 system Python?zsh/Users/jingwei/.pyenv/shims/python
shim 会查找当前目录/全局设置对应的 pyenv 版本。
解决方法:
zshpoetry new demo-project --python=/Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11
创建项目的同时,项目中会自动生成pyproject.toml 是 Poetry 项目的核心配置文件,该文件的用途是依赖管理、构建、打包、发布:
zsh# 查看pyproject.toml文件内容 nano pyproject.toml [project] name = "demo-project1" version = "0.1.0" description = "" authors = [ {name = "JingWei",email = "qi.zhang010711@gmail.com"} ] readme = "README.md" requires-python = ">=3.11" dependencies = [ ] [tool.poetry] packages = [{include = "demo_project1", from = "src"}] [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] build-backend = "poetry.core.masonry.api"
注意
在 Poetry 1.x 系列,pyproject.toml 里默认写的是:
zshpython = "^3.13"
Poetry 的模板文件里写死了最新的 Python 版本(目前 1.8.3 就是这样)。 所以它和你当前系统用的 Python 版本(不管是 pyenv local,还是 python --version)无关。 换句话说: poetry new 生成的 pyproject.toml 永远是个固定模板,不会根据你机器上的 Python 动态生成。
解决方法:
| 方法 | 操作命令 |
|---|---|
| 1. 手动修改(推荐) | 打开 pyproject.toml,改成:python = "^3.10" 或更精确:python = ">=3.10,<3.11" |
| 2. 自动化创建(Poetry 2.x 支持) | 在 Poetry 2.0+ 里,可以用:poetry init --python=3.10 这样生成的约束就是你指定的版本,而不是写死 ^3.13 |
pyproject.toml 配置说明
| 区域 | 内容 | 作用 |
|---|---|---|
[project] | PEP 621 标准,存放项目的基本元数据,其他工具也能读取(如 pip、build、tox) | |
name = "demo-project1" | 包名 | 项目的名字(在 PyPI 上的名称),发布时使用 |
version = "0.1.0" | 版本号 | 遵循 语义化版本规范,例如 major.minor.patch |
description = "" | 描述 | 项目的简要介绍 |
authors = [...] | 作者信息 | 作者列表,这里你设置了姓名 + 邮箱 |
readme = "README.md" | 说明文档 | 指定项目的 README 文件,会在 PyPI 展示 |
requires-python = ">=3.11" | Python 版本范围 | 限定支持的 Python 版本(这里是 3.11 及以上) |
dependencies = [] | 运行依赖 | 项目运行时所需的依赖包,发布到 PyPI 时会自动标注,在这里您可以列出项目需要的所有依赖包。 就像旧 requirements.txt 文件一样。 您可以手动完成此操作,然后调用命令 poetry install 以将其全部安装以用于软件包开发和工作目的。 如果您使用 poetry add <dependency_name>安装依赖包 相当于使用 pip install <dependency_name> |
| 区域 | 内容 | 作用 |
|---|---|---|
[tool.poetry] | Poetry 特有配置,扩展了 PEP 621 之外的功能 | |
packages = [{include = "demo_project1", from = "src"}] | 包路径配置 | 指定源码路径:包名是 demo_project1,它的源码位于 src 目录下。这是 “src 布局”,常见于中大型项目,可以避免 import 时混淆项目根目录与包目录。 |
| 区域 | 内容 | 作用 |
|---|---|---|
[build-system] | PEP 517/518 标准,声明项目的构建系统 | |
requires = ["poetry-core>=2.0.0,<3.0.0"] | 构建依赖 | 构建项目所需的依赖,这里使用 poetry-core(轻量化版本的 Poetry,不包含命令行) |
build-backend = "poetry.core.masonry.api" | 构建后端 | 告诉 Python 构建工具(如 pip install .)该如何构建项目 |
zsh# 进入现有项目目录(我的已有项目名称为PeotryDemo),初始化项目 cd PeotryDemo poetry init # 查看目录结构 tree PeotryDemo -a # 项目目录结构如下 PeotryDemo ├── .idea │ ├── .gitignore │ ├── inspectionProfiles │ │ ├── profiles_settings.xml │ │ └── Project_Default.xml │ ├── misc.xml │ ├── modules.xml │ ├── PeotryDemo.iml │ └── workspace.xml ├── main.py └── pyproject.toml 3 directories, 9 files
相关信息
由于我是通过Pycharm创建的项目,所有其中的.idea文件夹为IDE配置,非poetry生成的,poetry仅生成一个pyproject.toml文件。
在进行初始化的过程中,存在以下交互过程,整理如下:
| 提示语 | 你的输入 | 解释 |
|---|---|---|
| This command will guide you through creating your pyproject.toml config. | - | 说明这是一个交互式向导,会一步一步帮你生成 pyproject.toml |
| Package name [peotrydemo]: | PoetryDemo | 包名(默认取当前文件夹名),用于发布到 PyPI 的项目名,必须小写、无空格,建议保持一致:poetrydemo |
| Version [0.1.0]: | (回车,默认 0.1.0) | 项目的版本号,遵循 语义化版本 规则(major.minor.patch) |
| Description []: | 验证已有项目初始化 | 项目描述,显示在 PyPI 或文档中 |
| Author [JingWei qi.zhang010711@gmail.com, n to skip]: | (回车,默认) | 作者信息,可多人 |
| License []: | MIT | 许可证类型(如 MIT、Apache-2.0、GPL-3.0 等),会写入 pyproject.toml 并在 PyPI 展示 |
| Compatible Python versions [>=3.11]: | (回车,默认) | 指定兼容的 Python 版本,格式为 PEP 440 约束,比如 >=3.8,<3.12 |
| 提示语 | 你的输入 | 解释 |
|---|---|---|
| Would you like to define your main dependencies interactively? (yes/no) [yes] | yes | 是否现在添加 运行依赖(生产环境需要的依赖,比如 requests、flask) |
| You can specify a package in the following forms: | - | 支持多种依赖格式:包名、带版本约束、git 仓库、本地路径、远程 URL |
| Package to add or search for (leave blank to skip): | requests | 你输入了 requests,Poetry 会去 PyPI 搜索 |
| Found 152 packages matching requests | - | 找到了很多可能的候选包 |
| Enter package # to add... | 0 | 选择第一个(即官方 requests 包) |
| Enter the version constraint... | (回车,默认 latest) | 不填就自动选最新的稳定版,并加上 caret 约束(^),即兼容版本范围 |
| → Using version ^2.32.5 for requests | - | 代表安装 requests>=2.32.5,<3.0.0 |
| 提示语 | 你的输入 | 解释 |
|---|---|---|
| Would you like to define your development dependencies interactively? (yes/no) [yes] | (你回车 yes) | 是否添加 开发依赖(仅开发/测试需要,比如 pytest、black) |
| Package to add... | (回车跳过) | 没有额外开发依赖 |
| 提示语 | 生成内容 | 解释 |
|---|---|---|
| Generated file | pyproject.toml 内容 | 根据前面填写的内容生成配置文件 |
| Do you confirm generation? (yes/no) [yes] | yes | 确认写入 pyproject.toml |
zsh[project] name = "poetrydemo" # 包名(小写,最终写回默认) version = "0.1.0" # 项目版本 description = "验证已有项目初始化" # 项目描述 authors = [ {name = "JingWei",email = "qi.zhang010711@gmail.com"} ] license = {text = "MIT"} # 许可证 readme = "README.md" # README 文件 requires-python = ">=3.11" # Python 版本约束 dependencies = [ # 运行依赖 "requests (>=2.32.5,<3.0.0)" ] [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] # 构建依赖 build-backend = "poetry.core.masonry.api" # 构建后端
Pipenv/venv和Poetry在虚拟环境的“进入方式”上有一些差异:
zsh## 进入项目目录,显式的激活虚拟环境(所用的py解释器为系统的最高版本解释器) poetry shell ## 切换虚拟环境:若想指定py解释器,请修改pyproject.toml中的解释器版本之后,指定解释器激活环境,激活命令如下: poetry env use /Users/jingwei/.pyenv/versions/3.10.7/bin/python3.10 ## 查看虚拟环境信息 poetry env info ## 显示虚拟环境所有列表 poetry env list ## 显示虚拟环境绝对路径 poetry env list --full-path ## 退出虚拟环境 exit ## 查看py版本(未显性激活可查看) poetry run python -V ## 删除虚拟环境 1.可以直接删除虚拟环境文件夹 2.通过poetry env remove命令删除 poetry env remove python3
zsh## 进入项目目录,执行 poetry env activate ## 复制输出的 source .../bin/activate 命令,手动执行一次 source .../bin/activate ## 退出虚拟环境 deactivate ## 彻底退出并关掉窗口 exit
zsh# poetry add 安装依赖包 ## 安装最新版本的requests poetry add requests poetry add requests@2.30 # 精确锁死 2.30(不会自动更新到 2.31/2.32),poetry update无法升级 poetry add requests@^2.30 # 允许 2.x 的所有更新(直到 <3.0) poetry add requests@~2.30 # 允许 2.30.x 更新,但不能到 2.31 poetry add requests@>=2.30,<3.0 # 手工指定范围(等价于 ^2.30) ## 指定为开发依赖,会写到pyproject.toml中的[tool.poetry.dependencies]区域 poetry add pytest --dev # poetry install 安装pyproject.toml文件中的依赖 ## 安装pyproject.toml文件中的全部依赖 poetry install ## 仅安装非development环境的依赖,一般部署时使用 poetry install --no-dev ## 更新所有锁定版本的依赖包(慎用):开发时用 update,线上部署用 install(保证可复现环境) poetry update ## 更新指定依赖包 poetry update numpy ## 卸载依赖包 poetry remove numpy ## 查看可以更新的依赖 poetry show --outdated ## 查看项目安装的依赖 poetry show ## 以树形结构查看项目安装的依赖关系 poetry show --tree
本次上传,选择TestPYPi进行测试项目的构建与发布,在此之前需提前注册好账号并创建 API Token。
zsh## 项目打包 poetry build ## 在本地配置 Poetry 使用这个API Token,写入当前项目目录下的本地配置文件,不会影响其他项目,也不会写入全局用户配置。 poetry config pypi-token.testpypi <你的token> --local ## 发布项目打包文件 poetry publish -r testpypi
注意
zshHTTP Error 403: Forbidden | b"<html>\n <head>\n <title>403 The user 'LB6666' isn't allowed to upload to project 'poetry-demo'.
zshUsername/Password authentication is no longer supported. Migrate to API Tokens or Trusted Publishers instead
本文作者:精卫
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!