原文地址:alpopkes.com/posts/pytho… 作者在 EuroPython 2023 上关于这个的讲演:www.youtube.com/watch?v=3-d… 译者做的视频翻译版别:[EuroPyCon2023]客观点评与比照Python一切的依靠环境办理东西

背景常识

当我开端运用 Python 并创立我的第一个包时,我很困惑。创立和办理包好像比我料想的要困难得多。此外,存在多种东西,但我不确定该运用哪一种。我相信你们大多数人曩昔都遇到过同样的问题。Python 有无数的东西来办理虚拟环境和创立包,但很难(或几乎不或许)了解哪一个适合您的需求。存在一些关于该主题的讲演和博客文章,但它们都没有给出完整的概述或以结构化的方法点评这些东西。这便是这篇文章的主题。

东西分类

本文区分五个关于环境和包办理方面很重要的类别:

  • Python 版别办理
  • 包办理
  • 环境办理(首要触及虚拟环境)
  • 包构建
  • 包发布

正如下面的维恩图中所示,存在很多东西。有些是单一用处的,有些是多面手:

【翻译】客观点评与比照Python一切的依靠环境办理东西

让咱们从开发人员的角度来阅读一下这些类别:假设您一同处理个人项目和工作项目。在工作中,您运用的是 Python 3.7,而您的个人项目应该运用最新的 Python 版别(当时为 3.11)。换句话说:您期望可以装置不同的 Python 版别并在它们之间进行切换。这便是咱们的第一个类别,Python 版别办理的内容。

在您的项目中,您正在运用其他软件包(例如 pandas 或 sklearn 用于数据科学)。这些是您有必要装置和办理的项意图依靠项(例如,在发布新版别时进行升级)。这便是包办理的意义地点。

由于不同的项目或许需求同一包的不同版别,因而您需求创立(和办理)虚拟环境以防止依靠抵触。用于此意图的东西搜集在环境办理类别中。大多数东西运用虚拟环境,但有些东西运用另一个称为 “本地包”(Local Packages) 的概念,咱们稍后会讨论。

您或许期望与其他开发人员共享您的代码。为此,您首要有必要构建包(包构建),然后才能将其发布到 PyPI 或其他索引(包发布)。

下面咱们将更详细地了解每个类别,包括简短的界说、动机和可用的东西。我将在最后的单独部分中更详细地介绍一些单一用处东西和一些多用处东西。咱们先从第一类开端:Python 版别办理。

Python版别办理

界说

一个可以进行 Python 版别办理的东西,可以让你轻松装置 Python 版别并在它们之间切换。

动机

为什么咱们要运用不同的 Python 版别?有几个原因。例如,您或许正在处理多个项目,其间每个项目都需求不同的 Python 版别。或许,您或许开发一个支撑多个 Python 版别的项目,而且想要测验一切版别。除此之外,查看最新的 Python 版别所供给的功用,或许测验 Python 的预发布版别是否存在过错也是不错的挑选。

东西

咱们的维恩图显示了可用于 Python 版别办理的东西:pyenv, conda, rye 和 PyFlow。咱们将首要在单独的部分中查看 pyenv 并考虑多用处东西。

【翻译】客观点评与比照Python一切的依靠环境办理东西

Python 自带一个单一用处的东西,可让您装置和办理 Python 版别:pyenv!Pyenv 很容易运用。最重要的指令如下:

# 装置特定版别的 Python
pyenv install 3.10.4
# 在不同的 Python 版别之间切换
# 仅针对当时 shell 切换 Python 版别
pyenv shell <version> 
# 在这个目录下,自动运用某个 Python 版别
pyenv local <version> 
# 针对当时用户,全局设定 Python 版别
pyenv global <version> 

(虚拟)环境办理

界说

环境办理东西,答应您创立和办理(虚拟)环境。

动机

为什么咱们首要要运用环境?正如一开端提到的,项目有特定的要求(即它们依靠于其他包)。通常情况下,不同的项目需求同一包的不同版别。这或许会导致依靠抵触。此外,运用 pip install 装置包时或许会出现问题,由于该包与系统范围的 Python 装置一同放置。其间一些问题可以通过运用指令 –user 中的标志来处理。然而,这个选项或许并不是每个人都知道,尤其是初学者。

东西

许多东西答应用户创立和办理环境。它们是:venv, virtualenv, pipenv, conda, pdm, poetry, hatch, rye 和 PyFlow。其间只要两个是单一用处东西:venv 和 virtualenv。让咱们先来看看这两个:

【翻译】客观点评与比照Python一切的依靠环境办理东西

venv

venv(docs.python.org/3/library/v…) 是用于创立虚拟环境的内置 Python 包。最重要的指令如下:

# 创立一个新的环境
python3 -m venv <env_name>
# 运用这个环境
. <env_name>/bin/activate
# 封闭这个环境
deactivate

virtualenv

virtualenv (virtualenv.pypa.io/en/latest/)测验改进 venv. 它供给的功用更多,速度更快,功用更强大。最重要的指令与 venv 基本一样:

# 创立一个新环境
virtualenv <env_name>
# 启用这个环境
. <env_name>/bin/activate
# 封闭这个环境
deactivate

包办理

pyproject.toml

在咱们讨论打包之前,我想确保您了解打包最重要的文件:pyproject.toml.

Python 的打包现已取得了长足的前进,在 PEP 518 之前,setup.py 文件用于打包,setuptools 作为构建东西。PEP 518 引进了 pyproject.toml 文件的用法。因而,在创立包时一直需求一个 pyproject.toml 文件,用于界说项意图设置、界说元数据和许多其他内容。一个示例是 pandas 的 pyproject.toml 文件:

github.com/pandas-dev/…

[build-system]
# Minimum requirements for the build system to execute.
# See https://github.com/scipy/scipy/pull/12940 for the AIX issue.
requires = [
    "meson-python==0.13.1",
    "meson==1.2.1",
    "wheel",
    "Cython==3.0.5",  # Note: sync with setup.py, environment.yml and asv.conf.json
    # Any NumPy version should be fine for compiling.  Users are unlikely
    # to get a NumPy<1.25 so the result will be compatible with all relevant
    # NumPy versions (if not it is presumably compatible with their version).
    # Pin <2.0 for releases until tested against an RC.  But explicitly allow
    # testing the `.dev0` nightlies (which require the extra index).
    "numpy>1.22.4,<=2.0.0.dev0",
    "versioneer[toml]"
]
build-backend = "mesonpy"
[project]
name = 'pandas'
dynamic = [
  'version'
]
description = 'Powerful data structures for data analysis, time series, and statistics'
readme = 'README.md'
authors = [
  { name = 'The Pandas Development Team', email='pandas-dev@python.org' },
]
license = {file = 'LICENSE'}
requires-python = '>=3.9'
dependencies = [
  "numpy>=1.22.4; python_version<'3.11'",
  "numpy>=1.23.2; python_version=='3.11'",
  "numpy>=1.26.0; python_version>='3.12'",
  "python-dateutil>=2.8.2",
  "pytz>=2020.1",
  "tzdata>=2022.7"
]
classifiers = [
# 省掉后续

.lock 文件

还有一个关于打包很重要的文件:确定文件(xxx.lock)。pyproject.toml 包括笼统依靠联系,确定文件包括详细依靠联系。它记录了为项目装置的一切依靠项的确切版别(例如 pandas==2.0.3)。这使得项目在多个平台上具有可重复性,例如下面的 github.com/python-poet…

# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
[[package]]
name = "build"
version = "1.0.3"
description = "A simple, correct Python build frontend"
optional = false
python-versions = ">= 3.7"
files = [
    {file = "build-1.0.3-py3-none-any.whl", hash = "sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f"},
    {file = "build-1.0.3.tar.gz", hash = "sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b"},
]
[package.dependencies]
colorama = {version = "*", markers = "os_name == "nt""}
importlib-metadata = {version = ">=4.6", markers = "python_version < "3.10""}
packaging = ">=19.0"
pyproject_hooks = "*"
tomli = {version = ">=1.1.0", markers = "python_version < "3.11""}
[package.extras]
docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"]
test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"]
typing = ["importlib-metadata (>=5.1)", "mypy (>=1.5.0,<1.6.0)", "tomli", "typing-extensions (>=3.7.4.3)"]
virtualenv = ["virtualenv (>=20.0.35)"]

界说

包办理东西可以下载和装置库及其依靠项。

动机

为什么咱们需求包?包答应咱们界说模块的层次结构并运用”.”语法,例如 from package.module import my_function 轻松拜访模块。此外,它们还可以轻松地与其他开发人员共享代码。由于每个包都包括一个 pyproject.toml 界说其依靠项的文件,因而其他开发人员不必单独装置所需的包,而只需从其 pyproject.toml 文件中装置该包即可。

东西

许多东西可以履行包办理:pip, pipx, pipenv, conda, pdm, poetry, rye 和 PyFlow.

其间,pip 或许是最众所周知的,它也是这里的专门只用来做包办理的东西。

【翻译】客观点评与比照Python一切的依靠环境办理东西

Python 的规范包办理器是 pip(pip.pypa.io/en/stable/),它随 Python 一同供给,并答应您从 PyPI 和其他索引装置包。首要指令(或许是 Python 开发人员学习的第一个指令之一)是 pip install <package_name>

多用处东西

接下来进入非单一用处的东西

pipenv

顾名思义,pipenv 结合了 pip 和 virtualenv。它可以履行虚拟环境办理和包办理,正如咱们在维恩图中看到的那样:

【翻译】客观点评与比照Python一切的依靠环境办理东西

pipenv 引进两个附加文件:

  • Pipfile:是一个 toml 文件(类似于 pyproject.toml),用于界说项目依靠项
  • Pipfile.lock:答应确定性构建。它消除了对 requirements.txt 文件的需求,并通过确定操作自动办理。

最重要的pipenv指令是:

# 装置某个包
pipenv install <package_name>
# 在虚拟环境运转某个脚本
pipenv run <script_name.py>
# 启用虚拟环境
pipenv shell

Conda

Conda 是一个通用的包办理系统。这意味着它不限于 Python 包。Conda 是一个具有很多功用的巨大东西。存在很多教程和博客文章(例如官方的),因而我不会在这里详细介绍。可是,我想提一件事:虽然可以构建和发布包,但 conda 我没有将该东西包括在恰当的类别中。这是由于打包的 conda 工作方法略有不同,而且生成的包将是 conda 包。

【翻译】客观点评与比照Python一切的依靠环境办理东西

特征点评

接下来我将比较不同东西的以下维度的特点:

  • 该东西是否办理依靠联系?
  • 它是否解析/确定依靠联系?
  • 是否有洁净的构建/发布流程?
  • 它答应运用插件吗?
  • 它支撑 PEP 660(可修改装置:peps.python.org/pep-0660/)吗?PEP 660 是关于根据构建的可修改装置 pyproject.toml。当您运用装置软件包时,pip 您可以挑选运用 pip install -e package_name 来以可修改模式装置它。当您开发包并期望您的更改直接反映在您的环境中时,这是一个重要的功用。
  • 它支撑 PEP 621(项目元数据:peps.python.org/pep-0621/)吗?PEP 621 指定如何在 pyproject.toml 文件中写入项意图中心元数据。我增加这个评判维度是由于一个包(剧透:它是 poetry)当时不支撑此 PEP,但运用自己的方法来声明元数据。

Flit

Flit(flit.pypa.io/en/stable/)测验创立一种简单的方法将 Python 包和模块放在 PyPI 上。它有一个非常详细的用例:它旨在用于打包纯 Python 包(即没有构建过程的包)。它不关心任何其他任务:

  • Python版别办理:❌
  • 包办理:❌
  • 环境办理:❌
  • 构建包:✅
  • 发布包:✅

这也反映在咱们的维恩图中:

【翻译】客观点评与比照Python一切的依靠环境办理东西

  • 该东西是否办理依靠联系?❌
  • 它是否解析/确定依靠联系?❌
  • 是否有洁净的构建/发布流程?✅
  • 它答应运用插件吗?❌
  • 它支撑 PEP 660 吗?✅
  • 它支撑 PEP 621 吗?✅

首要指令有:

# 创立新的 pyproject.toml
flit init
# 构建并发布 
flit publish

Poetry

Poetry 是众所周知的东西。正如维恩图中所示,它可以履行除 Python 版别办理之外的一切操作:

  • Python版别办理:❌
  • 包办理:✅
  • 环境办理: ✅
  • 构建包:✅
  • 发布包:✅

【翻译】客观点评与比照Python一切的依靠环境办理东西

Poetry 不支撑 PEP 621。GitHub 上关于此问题的开放问题已有大约 1.5 年的时刻,但仍是没有处理(github.com/python-poet…)。

  • 该东西是否办理依靠联系?✅
  • 它是否解析/确定依靠联系?✅
  • 是否有洁净的构建/发布流程?✅
  • 它答应运用插件吗?✅
  • 它支撑 PEP 660 吗?✅
  • 它支撑 PEP 621 吗?❌

首要指令:

# 创立目录结构和 pyproject.toml
poetry new <project_name>
# 交互式创立 pyproject.toml
poetry init
# 从 pyproject.toml 装置依靠
poetry install

依靠办理:

# Add dependency
poetry add <package_name>

# Display all dependencies
poetry show --tree
运转代码
# Activate virtual env
poetry shell

# Run script within virtual env
poetry run python <script_name.py>

确定文件:初次装置软件包时,Poetry 会解析 pyproject.toml 文件中列出的一切依靠项并下载最新版别的软件包。一旦 Poetry 完结装置,它将一切包和下载的确切版别写入一个 poetry.lock 文件,将项目确定到这些特定版别。建议将确定文件提交到您的项目存储库,以便一切从事该项意图人员都被确定到相同版别的依靠项。要将依靠项更新到最新版别,请运用以下指令:

poetry update

构建/发布流程:

# 打包 (创立 `.tar.gz` 和 `.whl`)
poetry build
# 发布到 PyPI
poetry publish 

pdm

pdm 是一个相对较新的包和依靠项办理器(于 2019 年开端),遭到 Poetry 和 PyFlow 的启示。您会注意到,我在本文中并没有讨论 PyFlow。这是由于 PyFlow 不再活泼,这不再适合快速开展的打包东西领域。作为一种新东西,pdm 需求 Python 3.7 或更高版别。与其他东西的另一个区别是 pdm 答应用户挑选构建后端。

pdm 是唯一在本地包上完成 PEP 582 的东西(除 PyFlow 之外) ,这是完成环境办理的替代方法。请注意,此 PEP 最近被拒绝了。

从维恩图中可以看出,pdm 坐落 Poetry 旁边。这意味着它可以做除 Python 版别办理之外的一切事情:

【翻译】客观点评与比照Python一切的依靠环境办理东西

  • Python版别办理:❌
  • 包办理:✅
  • 环境办理: ✅
  • 构建包:✅
  • 发布包:✅

pdm 的首要指令与 poetry 类似。然而,现在的指令仍是比较少。例如,现在没有 pdm shell 或 pdm new

  • 该东西是否办理依靠联系?✅
  • 它是否解析/确定依靠联系?✅
  • 是否有洁净的构建/发布流程?✅
  • 它答应运用插件吗?✅
  • 它支撑 PEP 660 吗?✅
  • 它支撑 PEP 621 吗?✅

创立一个新项目

# 交互式创立 pyproject.toml 
pdm init
# 从 pyproject.toml 装置包
pdm install

依靠办理

# 增加依靠
pdm add <package_name>
# 展现一切依靠
pdm list --graph

运转代码

# 没有 shell 指令 
# 运用当时环境运转
pdm run python <script_name.py>

确定文件:pdm 的确定功用与 poetry 类似。初次装置软件包时,pdm 会解析 pyproject.toml 文件中列出的一切依靠项并下载最新版别的软件包。pdm 完结装置后,会将一切包及其下载的确切版别写入文件中 pdm.lock,从而将项目确定到这些特定版别。建议将确定文件提交到您的项目存储库,以便一切从事该项意图人员都被确定到相同版别的依靠项。要将依靠项更新到最新版别,请运用以下指令:

pdm update

构建/发布流程:

# 打包 (创立 `.tar.gz` 和 `.whl`)
pdm build
# 发布到 PyPI
pdm publish 

Hatch

Hatch(hatch.pypa.io/latest/):

  • Python版别办理:❌
  • 包办理:❌
  • 环境办理: ✅
  • 构建包:✅
  • 发布包:✅

值得注意的是,Hatch 的作者许诺将很快增加确定功用(github.com/pypa/hatch/…)。当您阅读本文时,请必须查看 Hatch 的最新版别,看看是否已完成此功用。

【翻译】客观点评与比照Python一切的依靠环境办理东西

  • 该东西是否办理依靠联系?❌
  • 它是否解析/确定依靠联系?❌
  • 是否有洁净的构建/发布流程?✅
  • 它答应运用插件吗?✅
  • 它支撑 PEP 660(可修改装置)吗?✅
  • 它支撑 PEP 621(项目元数据)吗?✅

创立一个新项目

# 创立目录结构以及 pyproject.toml
hatch new <project_name>
# 交互式创立项目
hatch new -i <project_name>
# 初始化现有项目或许创立 pyproject.toml
hatch new --init

依靠办理

# 没有 add 指令,依靠需求手动增加到 pyproject.toml
# 展现依靠
hatch dep show table

运转代码

# 启用虚拟环境
hatch shell
# 在虚拟环境运转脚本
hatch run python <script_name.py>

构建/发布流程

#  打包 (创立 `.tar.gz` 和 `.whl`)
hatch build
# 发布到 PyPI
hatch publish 

声明式环境办理:Hatch 的特别之处在于它答应您在文件中配置虚拟环境 pyproject.toml。此外,它还答应您专门为环境界说脚本。示例用例是代码格式化(hatch.pypa.io/1.1/config/…)。

Rye

Rye 最近由 Flask 结构的创立者 Armin Ronacher 开发(初次发布于 2023 年 5 月)。它遭到编程言语 Rust 的打包东西 rustup 和 cargo 的激烈启示。Rye 是用 Rust 编写的,可以履行维恩图中的一切任务:

【翻译】客观点评与比照Python一切的依靠环境办理东西

  • Python版别办理:✅
  • 包办理:✅
  • 环境办理: ✅
  • 构建包:✅
  • 发布包:✅

现在,Rye 没有插件接口。可是,由于定期发布新版别,因而将来或许会增加此内容。

  • 该东西是否办理依靠联系?✅
  • 它是否解析/确定依靠联系?✅
  • 是否有洁净的构建/发布流程?✅
  • 它答应运用插件吗?❌
  • 它支撑 PEP 660(可修改装置)吗?✅
  • 它支撑 PEP 621(项目元数据)吗?✅

创立一个新项目:

# 创立目录结构以及 pyproject.toml
rye init <project_name>
# 指定一个 Python 本本
rye pin 3.10

依靠办理:

# 增加依靠,可是还没有装置
rye add <package_name>
# 同步虚拟环境, 确定文件等等
# 在这个过程装置依靠
rye sync

运转代码:

# 启动虚拟环境
rye shell
# 运用虚拟环境运转脚本
rye run python <script_name.py>

构建/发布流程:

# 打包 (创立 `.tar.gz` 和 `.whl`)
rye build
# 发布到 PyPI
rye publish 

总结

Flit Poetry pdm Hatch rye
该东西是否办理依靠联系
它是否解析/确定依靠联系
是否有洁净的构建/发布流程
它答应运用插件吗
它支撑 PEP 660(可修改装置)吗
它支撑 PEP 621(项目元数据)吗