使用 Conda + Poetry 有意义吗?

Does it make sense to use Conda + Poetry?

将 Conda + Poetry 用于机器学习项目是否有意义?分享一下我(菜鸟)的理解,请指正或赐教:

据我了解,CondaPoetry 有不同的目的,但在很大程度上是多余的:

我的想法是同时使用两者并划分它们的角色:让 Conda 成为环境管理者,让 Poetry 成为包管理者。我的理由是(听起来)Conda 最适合管理环境,可用于编译和安装非 python 包,尤其是 CUDA 驱动程序(用于 GPU 功能),而 Poetry 比 Conda 更强大Python 包管理器。

通过在 Conda 环境中使用 Poetry,我设法相当轻松地完成了这项工作。诀窍是不使用 Poetry 来管理 Python 环境:我没有使用像 poetry shellpoetry run 这样的命令,只使用 poetry initpoetry install 等(激活 Conda 环境后)。

为了全面披露,我的 environment.yml 文件(针对 Conda)如下所示:

name: N

channels:
  - defaults
  - conda-forge

dependencies:
  - python=3.9
  - cudatoolkit
  - cudnn

我的 poetry.toml 文件看起来像这样:

[tool.poetry]
name = "N"
authors = ["B"]

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

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

老实说,我这样做的原因之一是我在没有 Conda 的情况下努力安装 CUDA(用于 GPU 支持)。

您觉得这个项目设计合理吗?

我有使用 Conda + Poetry 设置的经验,并且运行良好。我的大部分依赖项都在 pyproject.toml 中指定,但是当 PyPI 中没有某些东西时,或者使用 Conda 安装它更容易时,我将它添加到 environment.yml 中。而且,Conda作为虚拟环境管理器,与Poetry配合得很好:不需要使用poetry runpoetry shell,激活正确的Conda环境就够了。

创建可重现环境的技巧

  1. 添加 Poetry,可能带有版本号(如果需要),作为 environment.yml 中的依赖项,以便在 运行 conda create 时安装 Poetry,以及 Python 和其他 non-PyPI 依赖项。
  2. 添加 conda-lock,它可以为 Conda 依赖项提供锁定文件,就像您为 Poetry 依赖项提供 poetry.lock 一样。
  3. 考虑使用 mamba,它通常与 conda 兼容,但更擅长解决冲突,而且速度也更快。另一个好处是您设置的所有用户都将使用相同的包解析器,独立于 locally-installed 版本的 Conda。
  4. 默认情况下,使用 Poetry 添加 Python 依赖项。如果有理由通过 Conda 安装软件包(例如为了获得 CUDA-enabled 版本)。在这种情况下,最好在 environment.yml 中指定包的确切版本,并在安装后,在 Poetry 的 pyproject.toml 中添加具有相同版本说明的条目(没有 ^~ 版本号前)。这将让 Poetry 知道包在那里,不应该升级。
  5. 如果您使用提供相同包的不同渠道,则可能不清楚从哪个渠道下载特定包。一种解决方案是使用 :: 符号指定程序包的通道(请参阅下面的 pytorch 条目),另一种解决方案是启用 strict channel priority。不幸的是,在 Conda 4.x 中无法通过 environment.yml.
  6. 启用此选项
  7. 请注意 Python 添加 user site-packages to sys.path, which may cause lack of reproducibility if the user has installed Python packages outside Conda environments. One possible solution is to make sure that the PYTHONNOUSERSITE 环境变量设置为 True(或任何其他 non-empty 值)。

例子

environment.yml:

name: my_project_env
channels:
  - pytorch
  - conda-forge
  # We want to have a reproducible setup, so we don't want default channels,
  # which may be different for different users. All required channels should
  # be listed explicitly here.
  - nodefaults
dependencies:
  - python=3.10.*  # or don't specify the version and use the latest stable Python
  - mamba
  - pip  # pip must be mentioned explicitly, or conda-lock will fail
  - poetry=1.*  # or 1.1.*, or no version at all -- as you want
  - tensorflow=2.8.0
  - pytorch::pytorch=1.11.0
  - pytorch::torchaudio=0.11.0
  - pytorch::torchvision=0.12.0

# Non-standard section listing target platforms for conda-lock:
platforms:
  - linux-64

virtual-packages.yml(可以使用,例如,当我们希望 conda-lock 生成 CUDA-enabled 锁定文件,即使在没有 CUDA 的平台上):

subdirs:
  linux-64:
    packages:
      __cuda: 11.5

First-time 设置

如果您已经在目标环境之外安装了 conda-lockmambapoetry,则可以避免使用 bootstrap 环境并简化下面的示例。

# Create a bootstrap env
conda create -p /tmp/bootstrap -c conda-forge mamba conda-lock poetry='1.*'
conda activate /tmp/bootstrap

# Create Conda lock file(s) from environment.yml
conda-lock -k explicit --conda mamba
# Set up Poetry
poetry init --python=~3.10  # version spec should match the one from environment.yml
# Fix package versions installed by Conda to prevent upgrades
poetry add --lock tensorflow=2.8.0 torch=1.11.0 torchaudio=0.11.0 torchvision=0.12.0
# Add conda-lock (and other packages, as needed) to pyproject.toml and poetry.lock
poetry add --lock conda-lock

# Remove the bootstrap env
conda deactivate
rm -rf /tmp/bootstrap

# Add Conda spec and lock files
git add environment.yml virtual-packages.yml conda-linux-64.lock
# Add Poetry spec and lock files
git add pyproject.toml poetry.lock
git commit

用法

上面的设置可能看起来很复杂,但它可以以相当简单的方式使用。

创造环境

conda create --name my_project_env --file conda-linux-64.lock
poetry install

激活环境

conda activate my_project_env

正在更新环境

# Re-generate Conda lock file(s) based on environment.yml
conda-lock -k explicit --conda mamba
# Update Conda packages based on re-generated lock file
mamba update --file conda-linux-64.lock
# Update Poetry packages and re-generate poetry.lock
poetry update