尽管 Poetry 核心中的依赖解析器经过高度优化,对于大多数情况来说应该足够快,但对于某些依赖集,查找有效解决方案可能需要一些时间。
这是因为并非所有在 PyPI 上的库都正确声明了它们的元数据,因此无法通过 PyPI JSON API 获取这些信息。因此,Poetry别无选择,只能下载这些软件包并检查它们以获取必要的信息。这是一项代价十分高的操作,既占用了带宽又耗费了大量时间,这就是为什么这个过程看起来很漫长的原因。
目前来看,对此并没有绕过的方法。不过,如果你注意到 Poetry 正在下载某个软件包的多个版本,你可以通过在你的 pyproject.toml
文件中更严格地约束该软件包,从而减轻这个工作负担。这样一来,Poetry 就不必筛选那么多版本,这在某些情况下可能会显著加快锁定(dependency locking)的过程。
注意:
一旦 Poetry 在你的计算机上缓存了软件包版本的信息,依赖解析过程将会变得更快。这意味着在首次获取软件包信息后,后续的依赖解析将会更加迅速。
Poetry自身采用了"major.minor.micro"的版本命名规则,这符合PEP 440的规范。
版本命名遵循类似于Python的版本命名约定:
- 主版本号的增加(增加第一个数字)是为了表示有不兼容的变化,如果无法进行弃用周期并且用户需要执行手动步骤来迁移到下一个版本。
- 次版本号的增加(增加第二个数字)可能包括新功能、新的弃用项以及删除在先前次版本中弃用的功能。
- 微版本号的增加(增加第三个数字)通常只包括错误修复,微版本中不会删除已弃用的功能。
总体而言,Poetry遵循主.次.微版本的版本格式,并且版本的增加基于每个发布中引入的变化的性质。
由于其庞大的用户群体,即使对于大多数用户来说被认为不相关的小更改也可能在事后变成对某些用户的破坏性更改。坚持严格的语义化版本控制并且(几乎)总是增加主版本号而不是次版本号似乎是不可取的,因为此时次版本号将不再具有任何意义。
没有上限的版本约束,比如使用 *
或 >=3.4
,会允许更新到依赖的任何未来版本,包括可能破坏向后兼容性的主要版本。
一旦发布了你的包的一个版本,如果某个依赖关系破坏了向后兼容性,你就无法再调整它的依赖关系了,除非进行新的发布,但之前的版本仍然存在问题。(用户仍然可以通过自行限制来规避破坏的依赖关系。)
为了避免这样的问题,你可以在你的约束中定义一个上限,在测试了你的包与新的主要版本兼容后,你可以在新的发布中增加这个上限。
例如,可以使用 ^3.4
而不是 >=3.4
,它允许所有小于4.0的版本。^
操作符在遵循语义化版本规范的库中非常有效。
然而,在定义上限时,你的包的用户将无法将依赖更新到超出上限的版本,即使它不会造成任何问题并且与你的包完全兼容。你必须先发布一个带有增加上限的新版本。
如果你的包将被其他包中的库使用,最好避免上限,以避免不必要的依赖冲突(除非你已经确定依赖的下一个版本将破坏你的包)。如果你的包将用作应用程序,则可能值得定义一个上限。
支持tox。通过使用tox
的隔离和构建您可以与Poetry提供的符合PEP 517标准的构建系统结合使用。
因此,在您的pyproject.toml
文件中,如果尚不存在,请添加以下部分:
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
tox
可以通过多种方式进行配置,具体取决于要测试的代码和应该安装的依赖项。
用例 #1:
[tox]
isolated_build = true
[testenv]
deps =
pytest
commands =
pytest tests/ --import-mode importlib
tox
会创建一个项目的sdist
包,并使用pip
在一个新的环境中进行安装。因此,依赖项是由pip
解析的。
用例 #2:
[tox]
isolated_build = true
[testenv]
allowlist_externals = poetry
commands_pre =
poetry install --no-root --sync
commands =
poetry run pytest tests/ --import-mode importlib
tox
将创建项目的sdist
包,并使用pip
在一个新的环境中进行安装。因此,首先由pip
解析依赖项。但随后我们运行Poetry,它将安装已锁定的依赖项到该环境中。
用例 #3:
[tox]
isolated_build = true
[testenv]
skip_install = true
allowlist_externals = poetry
commands_pre =
poetry install
commands =
poetry run pytest tests/ --import-mode importlib
tox
不会执行任何安装。Poetry
会安装所有依赖项和当前包,并以可编辑的方式运行。因此,测试将针对本地文件而不是已构建和已安装的软件包运行。
tox介绍
Tox 是一个用于自动化和规范化 Python 项目测试的工具。它允许您定义和配置测试环境,确保您的项目在不同的 Python 版本和依赖环境下都能正常工作。以下是 Tox 的一些关键概念和用途:
- 测试环境隔离: Tox 可以创建虚拟环境,并在这些虚拟环境中运行您的测试。这有助于确保测试是在干净的环境中进行的,避免与全局 Python 安装或其他项目的依赖冲突。
- 多版本测试: Tox 支持在多个 Python 版本下运行测试,这对于确保项目与不同 Python 发行版的兼容性非常有用。
- 配置文件: 使用
tox.ini
文件,您可以定义项目的测试配置。这包括测试环境、依赖项和测试命令等。- 集成到持续集成(CI): Tox 可以轻松集成到 CI 系统中,确保在每次提交或拉取请求时都能运行测试。常见的 CI 平台,如Travis CI、Jenkins、GitHub Actions 等,都支持 Tox。
- 可扩展性: Tox 可以与其他测试工具集成,如 Pytest、Nose 等,以及其他构建系统和工具。
使用nox-poetry包在Nox会话中安装在poetry.lock
中指定的依赖项的锁定版本。
虽然Poetry会自动创建虚拟环境以始终与全局Python安装隔离,但有一些情况下可能是不必要和繁琐的,比如在使用容器时。
在这种情况下,您可以通过将virtualenvs.create
设置为false
来禁用此功能:
poetry config virtualenvs.create false
与pip不同,Poetry不仅解析当前环境中的Python。相反,它确保在pyproject.toml
中给定的Python版本范围内可以解析依赖关系。
假设您有以下pyproject.toml
:
[tool.poetry.dependencies]
python = "^3.7"
这意味着您的项目旨在与任何Python版本兼容>=3.7,<4.0
。每当尝试添加一个其Python要求不匹配整个范围的依赖关系时,Poetry都会通知您,例如:
The current project's supported Python range (>=3.7.0,<4.0.0) is not compatible with some of the required packages Python requirement:
- scipy requires Python >=3.7,<3.11, so it will not be satisfied for Python >=3.11,<4.0.0
通常,您将希望将项目的受支持的Python范围与失败的依赖关系的上限范围匹配。或者,如果知道它在所有版本中都不需要,则可以告诉Poetry仅为特定范围的Python版本安装此依赖项。
这样做是为了与更广泛的Python生态系统保持一致。
例如,如果Poetry为一个项目构建一个分发包,而该项目使用的版本不符合PEP 440的规范,第三方工具将无法正确解析该版本。
默认情况下,运行poetry install ...
需要你的源文件存在(包括“root”包和可能存在的任何目录路径依赖项)。这与Docker的缓存机制不兼容,因为对源文件的任何更改都会导致所有层(Dockerfile中的后续命令)重新运行。例如,你可能有一个类似以下的Dockerfile:
FROM python
COPY pyproject.toml poetry.lock .
COPY src/ ./src
RUN pip install poetry && poetry install --no-dev
一旦任何源文件发生更改,RUN层的缓存将被失效,这会导致如果你在src/中更改了任何文件,则需要重新安装所有第三方依赖项(可能是这些步骤中最慢的一步)。
为了避免这种缓存破坏,你可以将其拆分为两个步骤:
- 安装第三方依赖项。
- 复制你的源代码并只安装源代码。
FROM python
COPY pyproject.toml poetry.lock .
RUN pip install poetry && poetry install --no-root --no-directory
COPY src/ ./src
RUN poetry install --no-dev
这里使用的两个关键选项是--no-root
(跳过安装项目源代码)和--no-directory
(跳过安装任何本地目录路径依赖项,如果没有任何目录路径依赖项,你可以省略这个选项)。有关poetry install
可用选项的更多信息。
Poetry的默认HTTP请求超时为15秒,与pip一样。类似于PIP_REQUESTS_TIMEOUT
,可以设置POETRY_REQUESTS_TIMEOUT
(待正式发布的环境变量)来更改此值。