图书馆A需要Python 3.6。图书馆B依赖于图书馆A,但需要Python 3.9,图书馆C依赖于图书馆B,但需要与Python 3.6兼容的特定版本的图书馆A。
欢迎来到依赖地狱!
由于原生Python在没有外部数据科学包的情况下是垃圾,数据科学家经常发现自己陷入类似上述情况的进退两难的依赖关系。
像PIP、Conda或可笑的requirements.txt文件这样的工具无法解决这个问题。实际上,依赖噩梦很大程度上就是因为它们存在。因此,为了结束他们的痛苦,Python开源社区开发了一款迷人的工具,名为Poetry。
Poetry是一款全能的项目和依赖管理框架,在GitHub上拥有超过25k个星星。本文将介绍Poetry,并列出它为数据科学家解决的问题。
让我们开始吧。
安装
虽然Poetry可以作为一个库使用PIP进行安装,但建议将其安装到系统范围内,这样您可以在任何地方调用poetry
命令行界面。这是在类Unix系统(包括Windows WSL2)上运行安装脚本的命令:
curl -sSL https://install.python-poetry.org | python3 -
如果由于某种奇怪的原因您使用Windows Powershell,这是适合的命令:
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -
要检查Poetry是否正确安装,您可以运行:
$ poetry -v
Poetry(版本1.5.1)
Poetry还支持各种shell(如Bash,Fish,Zsh等)的选项卡完成。在此处了解更多。
1. 所有项目的一致结构
由于Poetry是一款全能工具,您可以从项目的开始到结束使用它。
在开始一个新项目时,您可以运行poetry new project_name
。它会创建一个几乎准备好作为Python软件包构建和发布到PyPI的默认目录结构:
$ poetry new binary_classification
在binary_classification中创建软件包binary_classification
$ ls binary_classification
README.md 二进制分类 pyproject.toml 测试
$ tree binary_classification/
binary_classification
├── pyproject.toml
├── README.md
├── binary_classification
│ └── __init__.py
└── tests
└── __init__.py
但是,我们作为数据科学家很少创建Python软件包,因此建议您自己开始项目并在其中调用poetry init
:
$ mkdir binary_classification
$ poetry init
命令行界面将询问一系列设置问题,但您可以将大部分问题留空,因为稍后可以更新:
init
命令将生成Poetry的最重要文件-pyproject.toml
。该文件包含一些项目元数据,但最重要的是它列出了依赖项:
$ cat pyproject.toml
[tool.poetry]
name = "binary-classification"
version = "0.1.0"
description = "A binary classification project with scikit-learn."
authors = ["Bex Tuychiev "]
readme = "README.md"
packages = [{include = "binary_classification"}]
[tool.poetry.dependencies]
python = "^3.9"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
现在,在tool.poetry.dependencies
下,唯一的依赖项是Python 3.9(我们将在后面学习^
是什么)。让我们用更多的库来填充它。
如果您想了解
pyproject.toml
文件中所有字段的含义,请跳到这里。
2. 依赖规范
为了安装项目的依赖项,您将不再直接使用PIP或Conda。相反,您将开始使用poetry add library_name
命令。
这是一个例子:
$ poetry add scikit-learn@latest
添加@latest
标志会从PyPI安装Sklearn的最新版本。也可以添加多个依赖项而不使用任何标志(约束):
$ poetry add requests pandas numpy plotly seaborn
add
的美妙之处在于,如果指定的软件包没有任何版本约束,它会找到所有解析的软件包的版本,即在安装时不会引发任何错误。它还会根据pyproject.toml
中已指定的依赖项进行检查。
$ cat pyproject.toml
[tool.poetry]
...
[tool.poetry.dependencies]
python = "^3.9"
numpy = "^1.25.0"
scikit-learn = "^1.2.2"
requests = "^2.31.0"
pandas = "^2.0.2"
plotly = "^5.15.0"
seaborn = "^0.12.2"
让我们尝试将numpy
降级到v1.24,看看会发生什么:
$ poetry add numpy==1.24
...
因为seaborn(0.12.2)依赖于numpy(>=1.17,1.24.0)...
版本解析失败。
Poetry不会允许这种情况发生,因为降级的版本会与Seaborn发生冲突。如果这是PIP或conda,它们会高兴地安装Numpy 1.24,并在噩梦开始时对我们微笑。
除了标准安装外,Poetry还提供了一种灵活的语法来定义版本约束。该语法允许您指定确切的版本,设置版本范围的边界(大于、小于或在之间),以及精确指定主要、次要或补丁版本。以下表格摘自Poetry文档(MIT许可证),用作示例。
插入符要求:
波浪线要求:
通配符要求:
有关更高级的约束规范,请访问Poetry文档的此页面。
3. 环境管理
Poetry的核心功能之一是以最高效的方式将项目环境与全局命名空间隔离开来。
当您运行poetry add library
命令时,会发生以下情况:
- 如果您在已经激活了虚拟环境的现有项目中初始化了Poetry,
library
将被安装到该环境中(可以是任何环境管理器,如Conda、venv等)。 - 如果您使用
poetry new
创建了一个空白项目,或者在未激活任何虚拟环境时使用init
初始化了Poetry,Poetry将为您创建一个新的虚拟环境。
当发生第二种情况时,结果环境将位于/home/user/.cache/pypoetry/virtualenvs/
文件夹下。Python可执行文件也将位于该文件夹中的某个位置。
要查看哪个Poetry创建的环境处于活动状态,可以运行poetry env list
命令:
$ poetry env list
test-O3eWbxRl-py3.6
binary_classification-O3eWbxRl-py3.9(已激活)
要在Poetry创建的环境之间切换,可以运行poetry env use
命令:
$ poetry env use other_env
您可以从这里了解更多关于环境管理的信息。
4. 完全可复现的项目
当运行add
命令时,Poetry将生成一个poetry.lock
文件。它不会指定版本约束,例如1.2.*
,而是锁定您正在使用的库的确切版本,例如1.2.11
。所有后续运行的poetry add
或poetry update
命令都将修改锁定文件以反映更改。
使用这样的锁定文件可以确保使用您的项目的人可以在他们的机器上完全复现环境。
人们长期以来一直使用诸如requirements.txt
的替代方案,但它的格式非常松散且容易出错。典型的人工创建的requirements.txt
不是很详细,因为开发人员通常不会费心列出他们正在使用的确切库版本,而只是给出版本范围,或者更糟糕的是,只是写下库名。
然后,当其他人尝试使用pip install -r requirements.txt
复现环境时,PIP本身会尝试解决版本约束,这就是你悄悄陷入依赖地狱的方式。
使用Poetry和锁定文件,这些问题都不会发生。因此,如果您在已经存在requirements.txt
的项目中初始化Poetry,可以使用以下命令将依赖项添加到其中:
$ poetry add `cat requirements.txt`
然后删除requirements.txt
文件。
但请注意,某些服务(如Streamlit或Heroku)仍然需要旧的requirements.txt
文件进行部署。在使用这些服务时,可以使用以下命令将poetry.lock
文件导出为文本格式:
$ poetry export --output requirements.txt
要遵循的工作流程
我希望用一套逐步工作流程来介绍如何将Poetry整合到任何数据项目中。
步骤0:为您的系统安装Poetry。
步骤1:使用mkdir
创建一个新项目,并在内部调用poetry init
来初始化Poetry。如果您想将项目稍后转换为Python包,请使用poetry new project_name
创建项目。
步骤2:使用poetry add lib_name
安装和添加依赖项。也可以手动编辑pyproject.toml
文件,并在[tool.poetry.dependencies]
部分下添加依赖项。在这种情况下,您必须运行poetry install
来解决版本约束并安装库。
完成此步骤后,Poetry将为项目创建一个虚拟环境并生成一个poetry.lock
文件。
步骤3:初始化Git和其他工具,如DVC,并开始跟踪适当的文件。将pyproject.toml
和poetry.lock
文件放入Git。
步骤4:开发您的代码和模型。要运行Python脚本,必须使用poetry run python script.py
,以便使用Poetry的虚拟环境。
步骤5:测试您的代码并进行任何必要的调整。对数据分析或机器学习算法进行迭代,尝试不同的技术,并根据需要完善您的代码。
可选步骤:
- 要更新已安装的依赖项,请使用
poetry update library
命令。update仅在pyproject.toml
中的约束条件内起作用,请检查此处的注意事项。 - 如果您要从具有requirements.txt的项目开始,请使用poetry add cat requirements.txt自动添加和安装依赖项。
- 如果要导出poetry.lock文件,可以使用
poetry export --output requirements.txt
。 - 如果为项目选择了软件包结构(使用
poetry add
),可以使用poetry build
构建软件包,准备推送到PyPI。 - 使用
poetry env use other_env
在虚拟环境之间切换。
通过这些步骤,您将确保再也不会陷入依赖关系的地狱。
感谢您的阅读!
Bex Tuychiev是VoAGI的十大人工智能作家和Kaggle Master,拥有超过15,000名粉丝。他喜欢以一种讽刺的风格编写关于复杂数据科学和机器学习主题的详细指南、教程和笔记本。
原文。经授权转载。