title: "Python 依赖管理工具的研究" date: 2023-01-19T08:05:27+08:00 categories: [Python] tags: [python]
如果你从事工程项目,poetry 是目前最好的方案,但是如果你不喜欢 Python 的 virtualenv,可以试试 pdm。
Python 的依赖管理工具 pip
一直被众多开发者吐槽。从我个人角度,pip
有三点致命缺陷:
requirements.txt
无法真正开箱即用Python 的依赖库可以安装到系统全局,也可以安装到用户目录(/home/${USER}/.local
)。但如果你同时管理多个 Python 项目,就需要将不同项目的依赖拆分到不同的文件夹分开管理。
传统方式是基于 virtualenv 创建隔离的 Python bin 文件和项目依赖的虚拟环境(所谓虚拟环境并不是虚拟机,只是个绑定 terminal session 的命令环境)。这种方式的缺点是:
Python 管理依赖的手段,最早是手动执行pip install xxx
来安装依赖,最后 pip freeze
来导出依赖列表到一个 requirements.txt
文件里。但是这个 txt 文件非常令人困惑。
pip install -r requirements.txt
得到的效果并不一致,经常报错。Python 一般使用 wheel
打包二进制,它只解决打包问题,环境依赖是靠 pip 和 setuptools 完成,所以使用 wheel 你仍然要操心环境隔离和依赖管理问题。
另外基于 Python 各版本之间兼容性问题和底层实现上的不可抗拒力量,wheel 也经常会莫名其妙失败。
一直以来,出现过 pipx
,pipenv
, conda
,poetry
以及我最近接触的 pdm
。他们都在某种程度上解决了 Python 的问题,这篇文章:
How to improve Python packaging, or why fourteen tools are at least twelve too many
对比了各种工具的利弊。最后得出结论是 poetry 和 pdm 是目前最合适的工具。而 pdm 是目前唯一支持 PEP 582 的依赖管理工具。
This PEP proposes to add to Python a mechanism to automatically recognize a
__pypackages__
directory and prefer importing packages installed in this location over user or global site-packages. This will avoid the steps to create, activate or deactivate “virtual environments”. Python will use the__pypackages__
from the base directory of the script when present.
这个 PEP 的目的就是基于一个文件夹 __pypackages__
来管理 Python 的依赖,类似 nodejs 的node_modules
,用户不需要再创建虚拟环境来隔离依赖包。Python 会自动识别和安装依赖。
更新于 2023 年 7 月 2 日:PEP 582 提案已经被拒绝,PDM 暂时仍然支持,但是不建议开发者使用这一特性。
PDM 实现了 PEP 582!这让我们在解决 Python 依赖问题时不用再考虑虚拟环境。
pdm init
之后 PDM 会问几个问题,记得选择不使用虚拟机环境,这样 PDM 就会默认使用 PEP 582 的解决方案,在项目下生成一个类似 NodeJS 的 __pypackages__
。
剩下的操作就跟 NodeJS 的 npm 非常像了。
添加一个依赖之后,PDM 会自动更新pyproject.toml
文件。
pdm add requests
pdm install
先在 pyproject.toml
里添加
[tool.pdm.scripts]
start = "flask run -p 54321"
然后执行
pdm run start
pdm build
pdm publish
如果你从事科研工作,用 conda
。
如果你从事工程项目,poetry
是目前业内用的最多的方案,大多数情况下它是个不错的依赖管理工具。但是如果你不喜欢 Python 的 virtualenv,pdm
是更好的选择。