一、起因

最近在逛一些当下比较热的python开源代码(fastapi、langchain、redash)的时候,发现项目根目录都很难见到requirments.txt这个包依赖文件了,取而代之的是pyproject.toml文件和poetry.lock文件。而我,还只会使用requirments.txt,来自程序员的直觉是,我已经落伍了,不由得一阵危机感,随之而来的是几个问题:

  1. pyproject.toml和poetry.lock这两个文件到底是啥?
  2. 为啥一线的开源项目都已经弃用requirments.txt?
  3. pyproject.toml和poetry.lock好在哪?

去python官网逛了一下,发现了 PEP518规范,是这么说的:

The build system dependencies will be stored in a file named pyproject.toml that is written in the TOML format
  • pyproject.toml是python官方推荐的新规范,用于描述python项目的依赖,取代了之前的requirments.txt,一个pyproject.toml文件大致长这样

    • 包含了代码库名称、版本、lisence等meta信息,还有python版本、依赖包的版本等信息,比原来干瘪瘪的requirments.txt是要丰富不少
  • poetry.lock则是用于管理python项目依赖关系的工具Poetry生成的文件。 它记录了项目所依赖的包的版本信息,帮助开发者在不同的开发环境中保持依赖的一致性,一个poetry.lock文件大致长这样

    • 描述了依赖包的版本、环境,以及依赖包的子依赖包的版本,甚至精确到了哈希值

那么这个Poetry是何方神圣,居然受到众多一线开源项目的青睐,应该不是花瓶,探一探究竟先。

于是照着Poetry官方文档操作了一波之后, 不禁感叹:这才是正经的包管理!

二、Poetry VS 传统包管理

1、自动生成、管理能够完整描述项目依赖的toml文件

  • 传统包管理

    • 以往经常会遇到一类情况,拿到一个项目,根据requirements.txt安装依赖的时候,由于requirements.txt缺乏对python版本的描述,导致接手的人不知道python版本
    • 之前有个项目是基于python3.8开发的,我选了当时还算比较新的python3.6,安装requirements.txt,然后运行报错,排查之后才发现是python版本不一致导致的问题
  • Poetry

    • 能解决以上问题,它会自动生成并管理pyproject.toml文件,生成代码库名称、版本、lisence等meta信息,还有python版本、依赖包的版本等信息

2、为生产和开发环境提供单独的依赖

  • 传统包管理

    • 一个场景是,开发、测试环境需要的包,生产环境不一定需要,比如pytest、flake8、black、pycodestyle等等,传统的做法是,建立多个requirements.txt,比如:requirements-dev.txt、requirements-test.txt、requirements-pro.txt,这样文件繁多,不利于统一管理
  • Poetry

    • 可以把所有环境的依赖比较好地区分,都放入pyproject.toml文件中统一管理

3、更新包版本,自动在pyproject.toml中同步更新

  • 传统包管理

    • 传统工具pip或者conda在更新或者添加包之后,需要手动或者pip freeze一下依赖,频繁更新容易忘记
  • Poetry

    • 将这个过程合二为一,只需要poetry add XXX,依赖信息会自动更新到pyproject.toml

4、依赖关系的解决

  • 传统包管理

    • 使用pip管理依赖比较大的一个痛点场景是,安装pandas==2.0.2,需要依赖numpy>=1.20.3,然后,你又安装了numpy==1.20.2,尽管发生了依赖冲突,pip依然会将numpy版本更新到1.20.2(与pandas==2.0.2对于numpy版本的要求冲突),这样,默默地引入依赖冲突的包,会在后续的程序运行中导致潜在的冲突问题,而且不太好排查解决。
  • Poetry

    • 会立即报错,并提示合理的版本区间

5、彻底删除已有依赖包以及子依赖包

  • 传统包管理

    • 使用pip管理依赖另一个比较大的痛点场景是,比如安装pandas==2.0.2的时候,顺带安装了包括numpy>=1.20.3在内的数十个子依赖,当你想要卸载pandas的时候,pip uninstall pandas,只会卸载pandas本身,而不会去卸载其下的数十个子依赖包,导致的问题就是,出现大量不会使用到的【孤儿】子依赖包,久而久之,包占用的空间【虚胖】,浪费存储空间,包管理也一团糟。
  • Poetry

    • 可以很好地管理依赖以及子依赖,删除依赖包的同时,一并删除子依赖,维护一个干净高效的项目环境。

三、总结

Poetry提供了比pip和conda更多的优势

  1. 一致的软件包安装:Poetry提供了一个一致的格式来安装任何软件包,确保整个项目有一个标准化的方法。
  2. 高效的依赖性管理:Poetry只为指定的软件包安装必要的依赖性,减少你环境中不相干的软件包的数量。
  3. 简化的软件包移除:Poetry简化了软件包及其相关依赖关系的移除,使其易于维护一个干净和高效的项目环境。
  4. 依赖性解决:Poetry的确定性解析器有效地解决了依赖关系,及时识别并处理任何不一致或冲突。

虽然Poetry可能需要团队成员花费一些额外的时间和精力来学习和适应,但从长远来看,使用Poetry这样的工具可以为你节省时间和精力。

给所有python开发安利这款神器。

四、号外

  • 看看隔壁,java(gradle.build)、前端开发(package.json),早都已经用上了现代化的包管理工具及规范,不得不感叹,python在机器学习、深度学习上确实拿捏了,但在工程化这方面,还是落后于别人家的小孩不止一点半点,工程化比较拉胯的另一个例子是,python直到最近一两年,随着fastapi的推广,才大范围用上swagger,极大地促进了接口开发联调效率,用过之后,不得不说,真香。

柚子
1 声望0 粉丝