使用 Python Poetry 进行依赖项管理(翻译)

本文最后更新于:2022年3月30日 早上

翻译信息

原文链接:https://realpython.com/dependency-management-python-poetry/

作者:Philipp Acsany

译者:muzing

翻译时间:2022.3

允许转载,转载必须保留全部翻译信息,且不能对正文有任何修改

当您的 Python 项目依赖于外部包时,需要确保使用每个包的正确版本。在一次更新之后,软件包可能无法像更新前那样工作。像 Python Poetry 这样的依赖管理器可帮助您在项目中指定、安装和解析外部包。这样,可以始终确保在每台机器上使用正确的依赖版本。

在本教程中,您将学到如何:

  • 开始一个新的 Poetry 项目
  • 添加 Poetry 到现有项目中
  • 使用 pyproject.toml 文件
  • 固定依赖项
  • 使用 poetry.lock 安装依赖
  • 运行基本的 Poetry 命令行命令

使用 Poetry 将帮助您启动新项目,维护现有项目,并控制依赖管理。您将准备好使用在 Python 项目中定义构建要求的标准—— pyproject.toml 文件。

为完成本教程并能充分使用它,您需要对虚拟环境模块与包pip 有基本的了解。

虽然本教程侧重于依赖管理,但 Poetry 还可以帮助您构建和打包项目。如果想分享您的作品,甚至可以将您的 Poetry 项目发布Python Packaging Index (PyPI)

处理预依赖

在深入了解 Python Poetry 的细节之前,需要先处理一些预依赖项。首先阅读关于本教程中将遇到的术语的简短概述,然后安装 Poetry 本身。

相关术语

如果曾在 Python 脚本中使用过 import 语句,那么就使用过模块(modules)。其中一些模块可能是您自己编写的 Python 文件。其他可能是内置模块,例如datetime。然而,有时 Python 提供的还不够,那么可能会转向外部的打包模块。当您的 Python 代码依赖于外部模块时,可以说这些包(packages)是您项目的依赖项(dependencies)

您可以在 PyPI 上找到不属于 Python 标准库的包。在了解其工作方式之前,您需要在系统上安装 Poetry。

安装 Python Poetry

要在命令行中使用 Poetry,应该在系统范围内安装它。如果只是想尝试一下,则可以使用 pip 将其安装到一个虚拟环境中。但应该谨慎尝试这种方法,因为 Poetry 会安装它自己的依赖项,这可能会与在项目中使用的其他包发生冲突。

译者注:翻译时根据 Poetry 官方文档,对本节内容有所更新:从 install-poetry 更新为 get-poetry 等。

安装 Poetry 的推荐方法是使用官方的 get-poetry 脚本。可以手动下载并运行此 Python 文件,也可以在下面选择您的操作系统以使用适当的命令:

Windows:

1
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python -

如果使用的是 Windows,则可以使用带有 -UseBasicParsing 选项的 Invoke-Webrequest cmdlet 将请求的 URL 的内容下载到标准输出流(stdout)。使用管道字符(|)可以将输出移交给 python标准输入流(stdin)。在此处,将 get-poetry.py 的内容管道到 Python 解释器。

macOS / Linux:

1
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 -

使用 curl 来将请求的 URL 的内容输出到标准输出流(stdout)。通过使用管道字符(|)的 Unix 管道,将输出移交给 python3标准输入流(stdin)。在本例中,将 get-poetry.py 的内容管道到 Python 解释器。

Note: 如果您使用的是 macOS,那么可能会收到一个 ssl.SSLCertVerificationError。如果您没有安装 SSL 模块的默认根证书(root certificates),则可能会发生此错误。可以通过在 Python 文件夹中运行命令脚本来安装它们:

1
open "/Applications/Python 3.9/Install Certificates.command"

根据您按照的 Python 版本,Python 解释器的特定路径可能会有所不同。在这种情况下,需要相应地调整上述命令中的路径。

运行命令后,上面的 curl 命令应该可以正常工作,没有任何错误。

在输出中应该会看到安装完成的消息。可以在终端中运行 poetry --version 以查看 poetry 是否正常工作。此命令将显示当前的 Poetry 版本。如果想更新 Poetry,那么可以运行 poetry self update

入门 Python Poetry

安装 Poetry 后,是时候看看 Poetry 是如何工作的了。在本节中,您将学习如何开始一个新的 Poetry 项目,以及如何将 Poetry 添加到现有项目中。您还将看到项目结构,并视察 pyproject.toml 文件。

创建一个新的 Poetry 项目

可以使用 new 命令和项目名称作为参数创建一个新的 Poetry 项目。在本教程中,项目名为 rp-poetry。创建项目,然后进入新创建的目录:

1
2
poetry new rp-poetry
cd rp-poetry

通过运行 poetry new rp-poetry,创建了一个名为 rp-poetry/ 的新文件夹。当查看文件夹内部时,会看到这样的结构:

1
2
3
4
5
6
7
8
9
10
11
rp-poetry/

├── rp_poetry/
│ └── __init__.py

├── tests/
│ ├── __init__.py
│ └── test_rp_poetry.py

├── README.rst
└── pyproject.toml

Poetry 会自动规范化包名称。它将项目中的破折号(-)转换为 rp_poetry/ 文件夹名称中的下划线(_)。否则,Python 中不允许使用该名称,因此无法将其作为模块导入。要更好地控制创建包名称,可以使用 --name 选项将其命名为与项目文件夹不同的名称:

1
poetry new rp-poetry --name realpoetry

如果希望将源代码存储在额外的 src/ 父文件夹中,则 Poetry 允许通过使用 --src 标志来遵守该约定:

1
2
poetry new --src rp-poetry
cd rp-poetry

通过添加 --src 标志,创建了一个名为 src/ 的文件夹,其中包含 rp_poetry/ 目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
rp-poetry/

├── src/
│ │
│ └── rp_poetry/
│ └── __init__.py

├── tests/
│ ├── __init__.py
│ └── test_rp_poetry.py

├── README.rst
└── pyproject.toml

创建新的 Poetry 项目时,将立即获得基本的文件夹结构。

检查项目结构

rp_poetry/ 子文件夹本身还不是很壮观。在这个目录中,有一个包含包版本的 __init__.py 文件:

1
2
3
# rp_poetry/__init__.py

__version__ = "0.1.0"

当跳到 tests/ 文件夹并打开 test_rp_poetry.py 时,会注意到 rp_poetry 已经可以导入了:

1
2
3
4
5
6
# tests/test_rp_poetry.py

from rp_poetry import __version__

def test_version():
assert __version__ == "0.1.0"

Poerty 还为该项目添加了第一个测试。test_version() 函数检查 rp_poetry/__init__.py__version__ 变量是否包含预期的版本。然而,__init__.py 文件并非定义包版本的唯一位置。另一个位置是 pyproject.toml 文件。

使用 pyproject.toml 文件

使用 Poetry 最重要的文件之一是 pyproject.toml 文件。这个文件不是 Poetry 的发明。这是 PEP 518 中定义的配置文件标准:

此 PEP 指定 Python 软件包应如何指定它们具有的构建依赖项以执行其选择的构建系统。作为本规范的一部分,为软件包引入了一个新的配置文件,用于指定它们的构建依赖项(期望相同的配置文件将用于未来的配置细节)。(

作者考虑了上文引用中提到的“新的配置文件”的几种文件格式。最后,他们决定采用 TOML 格式,它代表 Tom’s Obvious Minimal Language(Tom 的(语义)明显、(配置)最小化的语言)。在他们看来,TOML 足够灵活,比其他选项(YAML、JSON、CFG 或 INI)有更好的可读性和更低的复杂性。打开 pyproject.toml 文件来查看 TOML 的样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# pyproject.toml

[tool.poetry]
name = "rp-poetry"
version = "0.1.0"
description = ""
authors = ["Philipp <philipp@realpython.com>"]

[tool.poetry.dependencies]
python = "^3.9"

[tool.poetry.dev-dependencies]
pytest = "^5.2"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

可以在 pyproject.toml 文件中看到四个部分。这些部分被称之为表(tables)。它们包含 Poetry 等工具识别并用于依赖管理构建例程的说明。

如果表名称是基于特定工具的,则必须以 tool 为前缀。通过使用这样的子表(subtable),您可以为项目中的不同工具添加说明。在本例中,只有 tool.poetry。但您可能会在其他项目中看到例如为 pytest 使用的 [tool.pytest.ini_options] 等例子。

在上面第 3 行的 [tool.poetry] 子表中,可用存储关于该 Poetry 项目的一般信息。可用的键由 Poetry 定义。虽然有些键是可选项,但有四个是必须指定的:

  1. name:包的名称
  2. version:包的版本,最好遵循语义版本
  3. description:包的简短描述
  4. authors: 作者列表,格式为 name <email>

第 9 行的子表 [tool.poetry.dependencies] 和第 12 行的 [tool.poetry.dev-dependencies] 对依赖管理至关重要。在下一节添加依赖项到 Poetry 中时,您将了解到有关这些子表的更多内容。现在,重要的是认识到包依赖和开发依赖之间存在差异。

pyproject.toml 文件的最后一个表是第 15 行的 [build-system]。该表定义了 Poetry 和其他构建工具可以使用的数据,但由于它不是基于特定工具的,因此它没有前缀。Poetry 创建的 pyproject.toml 文件在该处包含两个键:

  1. requires: 构建包所需的依赖项列表,此键为必须项
  2. build-backend:用于执行构建过程的 Python 对象

如果想了解更多关于 pyproject.toml 文件这一节的信息,那么可以阅读 PEP 517 中的 source trees

当用 Poetry 开始一个新项目时,这是开始使用的 pyproject.toml 文件。随着时间的推移,将添加关于包和使用的工具的详细配置信息。随着 Python 项目的增长,pyproject.toml 文件也会随之增长。对于子表 [tool.poetry.dependencies][tool.poetry.dev-dependencies] 尤其如此。在下一节中,您将了解如何扩展这些子表。

使用 Python Poetry

一旦创建了一个 Poetry 项目,真正的工作就可以开始了。当 Poetry 就绪,就可以开始写代码。在此过程中,您将了解 Poetry 如何提供虚拟环境并处理依赖关系。

使用 Poetry 的虚拟环境

当开始一个新的 Python 项目时,最好创建一个虚拟环境。否则,可能会混淆来自不同项目的不同依赖项。使用虚拟环境是 Poetry 的核心功能之一,它永远不会干扰全局 Python 安装。

然而,Poetry 不会在创建项目时立即创建虚拟环境。可以通过让 Poetry 列出连接到当前项目的所有虚拟环境来确认 Poetry 还没有创建虚拟环境。如果还没有这样做,cd 进入 re-poetry/ 然后运行命令:

1
poetry env list

目前应该没有任何输出。

当运行一些命令时,Poetry 会一路创建一个虚拟环境。如果想更好的控制虚拟环境的创建,那么可能决定明确告知 Poetry 使用哪个 Python 版本,然后从那里开始:

1
poetry env use python3

使用此命令,将使用与安装 Poetry 相同的 Python 版本。当 PATH 中有 Python 可执行文件时,使用 python3 是有效的。

Note: 或者,可以传递一个 Python 可执行文件的绝对路径。它应该与可以在 pyproject.toml 文件中找到的 Python 版本约束相匹配。否则,可能会遇到麻烦,因为使用的 Python 版本与项目需要的版本不同。在您的环境中正常工作的代码在另一台机器上可能存在错误。

更糟糕的是,外部包通常依赖于特定的 Python 版本。因此,安装您的包的用户可能会收到错误,因为您的依赖版本与其 Python 版本不兼容。

当运行 env use 时,会看到一条消息:

1
2
Creating virtualenv rp-poetry-AWdWY-py3.9 in ~/Library/Caches/pypoetry/virtualenvs
Using virtualenv: ~/Library/Caches/pypoetry/virtualenvs/rp-poetry-AWdWY-py3.9

如您所见,Poetry 为项目环境创建了一个独特的名称。名称包含项目名和 Python 版本。中间看似随机的字符是父目录的哈希值。有了中间这个唯一的字符串,Poetry 可以在系统上处理多个具有相同名称和相同 Python 版本的项目。这很重要,因为默认情况下 Poetry 在同一个文件夹中创建所有虚拟环境。

无需其他任何配置,Poetry 会在 Poetry 的缓存目录virtualenvs/ 文件夹中创建虚拟环境:

操作系统 路径
macOS ~/Library/Caches/pypoetry
Windows C:\Users\<username>\AppData\Local\pypoetry\Cache
Linux ~/.cache/pypoetry

如果要更改默认缓存目录,则可以编辑 Poetry 的配置。当已经在使用 virtualenvwrapper 或其他第三方工具来管理虚拟环境时,这可能很有用。要查看当前配置,包括配置的 cache-dir,可以运行以下命令:

1
poetry config --list

通常不必更改此路径。如果想了解关于与 Poetry 虚拟环境交互的更多信息,那么 Poetry 文档包含有关管理环境的一章。

只要在项目文件夹中,Poetry 就会使用与之关联的虚拟环境。如果有任何疑惑,可以再次运行 env list 命令检查虚拟环境是否已激活:

1
poetry env list

这将显示 rp-poetry-AWdWY-py3.9 (Activated) 之类的内容。使用已激活的虚拟环境,您已经准备好开始管理一些依赖项并看到 Poetry 大放异彩。

声明你的依赖

Poetry 的一个关键元素是它对依赖项的处理。在开始之前,先看看 pyproject.toml 文件中的两个依赖表:

1
2
3
4
5
6
7
# rp_poetry/pyproject.toml (Excerpt)

[tool.poetry.dependencies]
python = "^3.9"

[tool.poetry.dev-dependencies]
pytest = "^5.2"

当前为项目声明了两个依赖项。一个是 Python 本身。另一个是 pytest,一个广泛使用的测试框架。正如您之前看到的,项目包含一个 tests/ 文件夹和一个 test_rp_poetry.py 文件。有 pytest 作为依赖项,Poetry 可以在安装后立即运行测试。

Note: 在编写本教程时,使用 Python 3.10 运行 pytest 不起作用。Poetry 安装了一个与 Python 3.10 不兼容的 pytest 版本。

Poetry 的开发者意识到了这个 issue,它将随着 Poetry 1.2 的发布而修复。

译者注:翻译时 Poetry 的最新稳定发布版为 Poetry version 1.1.13

确保正在 re-poetry/ 项目文件夹中,然后运行命令:

1
poetry install

使用 install 命令,Poetry 检查 pyproject.toml 文件中的依赖关系,然后解析并安装它们。当有许多依赖项又依赖于不同版本的不同第三方包时,解析部分尤其重要。在安装任何包之前,Poetry 会确定哪个版本的包满足其他包为它们的要求设置的版本约束。

除了 pytest 及其依赖项,Poetry 还安装了项目本身。这样,可以立即将 rp_poetry 导入到测试中:

1
2
3
4
5
6
# tests/test_rp_poetry.py

from rp_poetry import __version__

def test_version():
assert __version__ == "0.1.0"

安装项目的包后,可以将 rp_poetry 导入测试并检查 __version__ 字符串。安装 pytest 后,可以使用 poetry run 命令执行测试:

1
2
3
4
5
6
7
8
9
$ poetry run pytest
========================= test session starts ==========================
platform darwin -- Python 3.9.1, pytest-5.4.3, py-1.10.0, pluggy-0.13.1
rootdir: /Users/philipp/Real Python/rp-poetry
collected 1 item

tests/test_rp_poetry.py . [100%]

========================== 1 passed in 0.01s ===========================

当前测试成功运行,所以可以继续自信地写代码。然而,如果仔细查看第 3 行,会发现有些奇怪。它写的是 pytest-5.4.3,而不是 pyproject.toml 文件中规定的 5.2。问得好!

回顾一下,pyproject.toml 文件中的 pytest 依赖项如下所示:

1
2
3
4
# rp_poetry/pyproject.toml (Excerpt)

[tool.poetry.dev-dependencies]
pytest = "^5.2"

5.2 前面的插入符号(^)具有特定含义,它是 Poetry 提供的版本限制之一。这意味着 Poetry 可以安装与版本字符串最左侧的非零数字匹配的任何版本。这意味着允许使用 5.4.3。不允许使用版本 6.0

当 Poetry 尝试解析依赖版本时,像插入符号这样的符号将变得很重要。如果只有两个依赖项,这并不太难。声明的依赖项越多,它就越复杂。让我们看看 Poetry 如何通过将新包安装到项目中来解决这个问题。

使用 Poetry 安装 Python 包

您之前可以使用过 pip 来安装不属于 Python 标准库的包。如果使用包名作为参数运行 pip installpip 会在 Python 包索引(PyPI)上查找包。可以以同样的方式使用 Poetry。

如果想在项目中添加一个像 requests 这样的外部包,那么可以运行一个命令:

1
poetry add requests

通过运行 poetry add requests,将最新版本的 requests 库添加到项目中。如果想更具体,可以使用 requests<=2.1requests==2.24 等版本约束。当没有添加任何约束时,Poetry 将始终尝试安装最新版本的软件包。

有时只想在开发环境中使用某些包。pytest 正是其中之一。其他常见的库包括像 Black 这样的代码格式化工具,像 Sphinx 这样的文档生成器,以及像 PylintFlake8mypycoverage.py 这样的静态分析工具。

译者注:曾翻译过 Black 官方文档的大部分主要内容,见《五彩斑斓的 Black —— Python 代码格式化工具》

要明确告诉 Poetry 某个包是开发依赖项,可以使用 --dev 选项运行 poetry add。还可以使用简写的 -D 选项,等同于 --dev

1
poetry add black -D

添加了 requests 作为项目依赖和 black 作为开发依赖。Poetry 在后台为您做了一些事情。一方面,它将声明的依赖项添加到 pyproject.toml 文件中:

1
2
3
4
5
6
7
8
9
# rp_poetry/pyproject.toml (Excerpt)

[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.26.0"

[tool.poetry.dev-dependencies]
pytest = "^5.2"
black = "^21.9b0"

Poetry 将 requests 包作为项目依赖项添加到 tool.poetry.dependencies 表中,同时将 black 作为开发依赖项添加到 tool.poetry.dev-dependencies 中。

区分项目依赖项和开发依赖项可以防止用户安装非程序运行需要的依赖项。开发依赖项仅与包的其他开发者相关,他们希望使用 pytest 运行测试并确保使用 black 正确格式化代码。当用户安装包时,他们只安装 rquests

Note: 可以更进一步声明可选依赖项。当想让用户选择安装非必须但是可以增强包性能的特定数据库适配器时,这可能会很方便。可以在Poetry 文档中了解有关可选依赖项的更多信息。

除了对 pyproject.toml 文件的修改之外,Poetry 还创建了一个名为 poetry.lock 的新文件。在此文件中,Poetry 会跟踪在项目中使用的所有包和确切版本。

处理 poetry.lock

当运行 poetry add 命令时,Poetry 会自动更新 pyproject.toml,并将解析的版本固定在 poetry.lock 文件中。然而不必让 Poetry 完成所有工作。可以手动将依赖项添加到 pyproject.toml 文件中,并在这之后锁定它们。

poetry.lock 中固定依赖项

如果想用 Python 构建一个网络爬虫,那么可能像使用 Beautiful Soup 来解析数据。将其添加到 pyproject.toml 文件中的 tool.poetry.dependencies 表中:

1
2
3
4
5
6
# rp_poetry/pyproject.toml (Excerpt)

[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.26.0"
beautifulsoup4 = "4.10.0"

通过添加 beautifulsoup4 = "4.10.0",告知 Poetry 应该安装这个版本。当向 pyproject.toml 文件添加需求时,它尚未安装。只要项目中没有 poetry.lock 文件,可以在手动添加依赖项后运行 poetry install,因为 Poetry 首先查找 poetry.lock 文件。如果找不到,Poetry 会解析 pyproject.toml 文件中列出的依赖项。

一旦 poetry.lock 文件存在,Poetry 将依赖此文件来安装依赖项。只运行 poetry install 会触发两个文件不同步的警告,并且会产生错误,因为 Poetry 还不知道项目中的任何 beautifulsoup4 版本。

要将 pyproject.toml 文件中的依赖项固定到 poetry.lock,必须首先运行 poetry lock 命令:

1
2
3
4
5
$ poetry lock
Updating dependencies
Resolving dependencies... (1.5s)

Writing lock file

通过运行 poetry lock,Poetry 会处理 pyproject.toml 文件中的所有依赖项并将它们锁定到 poetry.lock 文件中。Poetry 并不止步于此。当运行 poetry lock 时,Poetry 也会递归地遍历并锁定直接依赖项的所有依赖项。

Note: 如果有适合当前版本约束的更新版本可用,poetry lock 命令还会更新现有的依赖项。如果不想更新 poetry.lock 文件中已经存在的任何依赖项,则必须向 poetry lock 命令中添加 --no-update 选项:

1
2
$ poetry lock --no-update
Resolving dependencies... (0.1s)

在这种情况下,Poetry 仅解析新的依赖项,同时保留 poetry.lock 文件中的所有现有依赖项版本不变。

现在已经固定了所有依赖项,是时候安装它们以便可以在项目中使用了。

poetry.lock 安装依赖项

如果您按照上一节中的步骤进行操作,那么已经使用 poetry add 命令安装了 pytestblack。也锁定了 beautifulsoup4,但还没有安装 Beautiful Soup。要验证 beautifulsoup4 是否尚未安装,使用 poetry run 命令打开 Python 解释器

1
poetry run python3

执行 poetry run python3 将在 Poetry 的环境中打开一个交互式 REPL 会话。首先尝试导入 requests。这应该完美运行。然后尝试导入 bs4,这是 Beautiful Soup 的模块名称。这应该会抛出一个错误,因为 Beautiful Soup 尚未安装:

1
2
3
4
5
>>> import requests
>>> import bs4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'bs4'

正如预期的那样,可以顺利地导入 requests,并且找不到模块 bs4。通过键入 exit() 并按下 Enter 退出交互式 Python 解释器。

使用 poetry lock 命令锁定依赖项后,必须运行 poetry install 命令才能在项目中实际使用它们:

1
2
3
4
5
6
7
8
9
$ poetry install
Installing dependencies from lock file

Package operations: 2 installs, 0 updates, 0 removals

• Installing soupsieve (2.2.1)
• Installing beautifulsoup4 (4.10.0)

Installing the current project: rp-poetry (0.1.0)

通过运行 poetry install,Poetry 读取 poetry.lock 文件并安装其中声明的所有依赖项。现在,bs4 已经在项目中可用了。要对此进行测试,输入 poetry run python3 并将 bs4 导入 Python 解释器:

1
2
3
>>> import bs4
>>> bs4.__version__
'4.10.0'

完美!这次没有错误,且是声明的确切版本。这意味着 Beautiful Soup 已经正确固定在 poetry.lock 文件中,已经安装在项目中,并且可以使用了。要列出项目中可用的包并检查它们的详细信息,可以使用 show 命令。当加上 --help 标志运行它时,可以看到如何使用:

1
poetry show --help

要检查一个包,可以将包名作为参数之一使用 show,或者可以使用 --tree 选项来树状列出所有依赖项。这将有助于查看项目的嵌套依赖项。

更新依赖

为了更新依赖关系,Poetry 根据两种情况提供了不同的选项:

  1. 更新版本约束内的依赖项。
  2. 更新版本约束外的依赖项。

可以在 pyproject.toml 文件中找到版本约束。当依赖项的新版本仍然满足该版本约束时,可以使用 update 命令:

1
poetry update

update 命令将更新所有包及其版本限制内的依赖项。之后,Poetry 会更新 poetry.lock 文件。

如果要更新一个或多个特定包,则可以将它们列为参数:

1
poetry update requests beautifulsoup4

使用此命令,Poetry 将搜索满足 pyproject.toml 文件中列出的版本约束的 requests 的新版本和 beautifulsoup4 的新版本。然后它将解析项目的所有依赖项并将版本固定到 poetry.lock 文件中。pyproject.toml 将保持不变,因为列出的约束仍然有效。

如果想用比 pyproject.toml 文件中定义的版本更高的版本更新依赖项,则需要事先调整 pyproject.toml 文件。另一种选项是运行带有版本约束或 latest 标记的 add 命令:

1
poetry add pytest@latest --dev

当运行带有 latest 标记的 add 命令时,它会查找最新版本的包并且更新 pyproject.toml 文件。包含 latest 标记或版本约束对使用 add 命令至关重要。没有它,则会收到一条包已经存在于项目中的消息。另外,不要忘记为开发依赖项添加 --dev 标记。否则会将包添加到常规依赖项中。

添加新版本后,必须运行在上一节中介绍的 install 命令。这有这样,更新才会锁定到 poetry.lock 文件中。

如果不确定更新会为依赖项引入哪些基于版本的更改,可以使用 --dry-run 标记。此标记适用于 updateadd 命令。它在终端中显示操作,但并不执行。这样,可以安全地查看版本更改并确定最合适的更新方案。

pyproject.tomlpoetry.lock 的区别

虽然 pyproject.toml 文件中的版本要求可能很宽松,但 Poetry 会在 poetry.lock 文件中锁定实际使用的版本。这就是如果使用 Git 则应该 commit 此文件的原因。通过在 Git 存储库中提供 poetry.lock 文件,可以确保所有开发者都使用相同版本的依赖包。当遇到包含 poetry.lock 文件的存储库时,使用 Poetry 是明智之举。

使用 poetry.lock,可以确保使用的版本与其他开发者正在使用的版本完全相同。如果其他开发者没有使用 Poetry,可以将其添加到未使用 Poetry 设置的现有项目中。

添加 Poetry 到现有项目中

很有可能,您的项目并不是使用 poetry new 命令开始的。或者也行您继承了一个不是用 Poetry 创建的项目,但是现在想用 Poetry 进行依赖管理。在这些类型的情况下,可以将 Poetry 添加到现有的 Python 项目中。

pyproject.toml 添加到脚本文件夹

如果项目仅包含一些 Python 文件,那么仍然可以添加 Poetry 作为未来构建的基础。在这个例子中,只有一个文件,hello.py

1
2
3
# rp-hello/hello.py

print("Hello World!")

该脚本唯一做的事情是输出字符串 "Hello World!"。但也许这只是一个宏大项目的开始,所以决定将 Poetry 添加到项目中。使用 poetry init 替代之前的 poetry new 命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ poetry init

This command will guide you through creating your pyproject.toml config.

Package name [rp-hello]: rp-hello
Version [0.1.0]:
Description []: My Hello World Example
Author [Philipp <philipp@realpython.com>, n to skip]:
License []:
Compatible Python versions [^3.9]:

Would you like to define your main dependencies interactively? (yes/no) [yes] no
Would you like to define your development dependencies interactively? (yes/no) [yes] no
Generated file

poetry init 将启动交互式会话以创建 pyproject.toml 文件。Poetry 为您提供了大多数需要设置的配置项的建议,可以按 Enter 键使用它们。当不声明任何依赖项时,Poetry 创建的 pyproject.toml 文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# rp-hello/pyproject.toml

[tool.poetry]
name = "rp-hello"
version = "0.1.0"
description = "My Hello World Example"
authors = ["Philipp <philipp@realpython.com>"]

[tool.poetry.dependencies]
python = "^3.9"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

内容与在前几节中介绍的示例相似。

现在可以使用 Poetry 项目提供的所有命令。有了 pyproject.toml 文件,现在可以运行脚本:

1
2
3
$ poetry run python3 hello.py
Creating virtualenv rp-simple-UCsI2-py3.9 in ~/Library/Caches/pypoetry/virtualenvs
Hello World!

因为 Poetry 没有找到任何可以使用的虚拟环境,所以它在执行脚本之前创建了一个新环境。完成此操作后,它会显示 Hello World! 消息而不出现任何错误。这意味着现在有一个有效的 Poetry 项目。

使用现有的 requirements.txt 文件

有时项目已经有一个 requirements.txt 文件。看看这个 Python 网络爬虫requirements.txt 文件:

1
2
3
4
5
6
7
8
$ cat requirements.txt
beautifulsoup4==4.9.3
certifi==2020.12.5
chardet==4.0.0
idna==2.10
requests==2.25.1
soupsieve==2.2.1
urllib3==1.26.4

使用 cat 实用程序,可以读取文件并将内容写入标准输出(stdout)。在本例中,它显示了网络爬虫项目的依赖关系。一旦用 poetry init 创建了 Poetry 项目,可以将 cat 实用程序与 poetry add 命令结合起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ poetry add `cat requirements.txt`
Creating virtualenv rp-require-0ubvZ-py3.9 in ~/Library/Caches/pypoetry/virtualenvs

Updating dependencies
Resolving dependencies... (6.2s)

Writing lock file

Package operations: 7 installs, 0 updates, 0 removals

• Installing certifi (2020.12.5)
• Installing chardet (4.0.0)
• Installing idna (2.10)
• Installing soupsieve (2.2.1)
• Installing urllib3 (1.26.4)
• Installing beautifulsoup4 (4.9.3)
• Installing requests (2.25.1)

当需求文件像这样简单时,使用 poetry addcat 可以节省一些手动工作。

然而有时 requirements.txt 文件有些复杂。在这些情况下,可以执行测试运行并查看结果,或者手动将需求添加到 pyproject.toml 文件中的 [tool.poetry.dependencies] 表中。要查看 pyproject.toml 的结构是否有效,可以在之后运行 poetry check

poetry.lock 创建 requirements.txt

在某些情况下,必须要有一个 requirements.txt 文件。例如,您也许想在 Heroku 上托管 Django 项目。对于这种情况,Poetry 提供了 export 命令。如果已有一个 Poetry 项目,可以从 poetry.lock 文件创建一个 requirements.txt 文件:

1
poetry export --output requirements.txt

以这种方式使用 poetry export 命令会创建一个 requirements.txt 文件,其中包含哈希值环境标记(environment markers)。这意味着可以确保使用类似于 poetry.lock 文件内容的非常严格的要求。如果还想包含开发依赖项,可以将 --dev 添加到命令中。要查看所有可用选项,可以查看 poetry export --help

命令参考

本教程介绍了 Poetry 的依赖管理。在此过程中,使用了 Poetry 的一些命令行界面(CLI)命令:

Poetry 命令 解释
$ poetry --version 显示 Poetry 安装版本。
$ poetry new 创建一个新的 Poetry 项目。
$ poetry init 将 Poetry 添加到一个现有项。
$ poetry run 使用 Poetry 执行给定的命令。
$ poetry add 将一个包添加到 pyproject.toml 并安装它。
$ poetry update 更新项目的依赖项。
$ poetry install 安装依赖项。
$ poetry show 列出已安装的包。
$ poetry lock 将最新版本的依赖项固定到 poetry.lock 中。
$ poetry lock --no-update 刷新 poetry.lock 文件而不更新任何依赖版本。
$ poetry check 验证pyproject.toml
$ poetry config --list 显示 Poetry 配置。
$ poetry env list 列出项目的虚拟环境。
$ poetry export poetry.lock 导出为其他格式。

可以查看 Poetry CLI 文档以了解有关上述命令和 Poetry 提供的其他命令的更多信息。还可以在终端中运行 poetry --help 查看信息!

总结

在本教程中,您探索了如何创建新的 Python Poetry 项目以及如何将 Poetry 添加到现有项目中。Poetry 的一个关键部分是 pyproject.toml 文件。结合 poetry.lock,可以确定安装项目所需的每个包的确切版本。当在 Git 存储库中跟踪 poetry.lock 文件时,还可以确保项目中的所有其他开发者在他们的机器上安装相同的依赖项版本。

在本教程中,您学习了如何:

  • 开始一个新的 Poetry 项目
  • 添加 Poetry 到已有项目中
  • 使用 pyproject.toml 文件
  • 固定依赖项
  • 使用 poetry.lock 安装依赖项
  • 执行基本的 Poetry CLI 命令

本教程侧重于 Poetry 依赖管理的基础知识,但 Poetry 还可以帮助您构建和上传您的包。如果想体验一下这个功能,那么可以阅读关于如何在将开源 Python 包发布到 PyPI 时使用 Poetry。


使用 Python Poetry 进行依赖项管理(翻译)
https://muzing.top/posts/3fa905f9/
作者
Muzing
发布于
2022年3月29日
更新于
2022年3月30日
许可协议