Python 的打包现状(写于 2019 年)
在这篇文章中,我将会试着给你讲清楚 python 打包那些错综复杂的细节。我在过去的两个月中,使用每天晚上精力最好的黄金时段尽可能多的收集相关信息、如今的解决方案,并搞清楚哪些是遗留的问题。
含糊不清的 python 术语是导致混乱的第一个来源。在编程相关的语境中,“包”(package)这个词意味着一个可以安装的组件(比如可以是一个库)。但是在 python 中却不是这样,在这里,可安装组件的术语是“发行版”(distribution)。但是,除非必要(特别是在官方文档和 Python 增强提案中),否则根本没人真的去用“发行版”这个术语。顺便说一下,使用这个术语其实是个非常糟糕的选择,因为“distribution”一词一般用来描述 Linux 的一个 brand。
这是一个你应该牢记于心的警告,因为 python 打包其实并不真的是关于 python 的包,而是关于它的发行版。但是我还是称之为打包。
我不想花那么多时间去阅读。能不能给我个简短的版本?在 2019 年,我应该如何管理 python 包呢?
我假设你是一名想要开始研发一个 python 包程序员,步骤如下:
- 首先使用 Poetry 创建开发环境,并使用严格模式指定项目的直接依赖。这样就可以保证你的研发和测试环境总是可以被重复创建的。
- 创建一个 pyproject.toml 文件,然后使用 poetry 作为后端创建源代码版和二进制发行版。
- 下一步要指定抽象包依赖。注意应指定你能确定的该包可运行的最低版本。这样就可以保证不会创建出无用的、会和其他包冲突的版本。
如果你真的想使用需要 setuptools 的老方法:
- 创建 setup.py 文件,在文件中指定所有的抽象依赖,并在 install_requires 中指定这些依赖使用可工作的最低版本。
- 创建
requirements.txt
文件,在其中指定严格、具体(即指定某个版本)、直接的依赖。接下来你将会需要使用这个文件生成实际的工作环境。 - 使用命令
python -m venv
创建一个虚拟环境,激活该环境然后在该环境下使用pip install -rrequirements.txt
命令安装依赖。用这个环境来开发。 - 如果你需要用于测试的依赖(当然这也是非常有可能的事情),那么你需要创建一个
dev-requirements.txt
文件,并同样为其安装依赖。 - 如果你需要将所有环境配置冻结(这是推荐的做法),执行
pip freeze >requirements-freeze.txt
并且以后也要用这个命令创建环境。
我的时间很充裕。请帮我解释清楚吧。
首先我将阐述目前存在的问题,真的有很多问题。
假设我想要用 python 创建某“项目”:它也许是一个独立程序,也许是一个库。这个项目的开发和使用需要包含以下“角色”:
- 开发者:负责写代码的人或者团队。
- CI:测试这个项目的自动化过程。
- 构建:从我们的 git 仓库到其他人可以安装使用这个项目的自动或半自动过程。
- 最终用户:最终使用这个项目的人或者团队。如果这个项目是一个库,那么最终用户也许是其他开发者;或者如果是一个应用,最终用户可能就是普通民众。又或者这个项目是某一种网络服务,那么最终用户就是云计算微服务。当然还有很多可能,你明白我的意思,不一一列举了。
我们的目标就是让所有的用户或者设备对该项目满意,但是他们都有不同的工作流和需求,并且有时候这些需求会有重叠的部分。另外,当项目发生更改、发布新版本、废除旧版本,或者几乎所有代码都要依赖其他代码来完成其任务的时候会产生问题。项目中必定存在依赖,而随着时间推移,这些依赖会发生变化,它们也许是必要的也许也不是,它们可能在很底层运行,所以我们必须考虑在不同操作系统甚至在同样的操作系统