返回介绍

9.2 巧用程序包

发布于 2024-01-21 17:11:03 字数 4468 浏览 0 评论 0 收藏 0

在需要多次重复安装的时候,wheel 格式的程序包显得十分便捷。接下来我们学习一下如何将其巧用到 CI 和部署中去。

9.2.1 私密发布

有时候我们需要用到未在 PyPI 上公开的程序包,比如不能在 PyPI 上公开的公司内部库,或者一些经过修改但尚未正式发布的库等。

这种时候,可以借助版本库服务器提供的功能做私密发布。私密发布一般用来做程序包公开到 PyPI 前的测试,以及给一些不想添加到 PyPI 但仍需安排版本号的程序包做内部公开。前面我们学习了直接从版本库进行安装的方法,使用者可以通过这个方法获取目标版本的程序包,其过程与程序包作者本人的意图基本无关。

Github 和 Bitbucket 会以标签名或分支名为单位提供 zip 或其他格式的源码文件。同时,通过使用 pip 指定包含程序包名称的完整 URL,可以绕过索引服务器直接安装程序包。将这两个组合在一起,我们就能安装已私密发布但尚未在 PyPI 发布的程序包了。

举个例子,有个名为 logfilter 的工具,其源码在 Bitbucket 中公开管理。这个工具并未在 PyPI 上公开程序包,因此不能通过 pip install logfilter 进行安装。但是,如果我们像 LIST 9.6 这样直接指定 URL,就能够完成安装了。

LIST 9.6 安装已私密发布的程序包

$ pip install https://bitbucket.org/shimizukawa/logfilter/get/logfilter-0.9.2.zip

9.2.2 巧用 requirements.txt

用 pip freeze 命令可以查看通过 pip 安装的依赖库的内容。如果将这些内容保存在文件中,再用 pip install 的 -r 选项指定这个文件,在该环境中安装的库就可以在其他环境中被还原。

$ pip freeze > requirements.txt
$ pip install -r requirements.txt

多数项目都将依赖库的列表保存在了 requirements.txt 文件中。不过,requirements.txt 能做的事还远不止于此。

requirements.txt 内部可以引用其他 requirements.txt。比方说我们要把只在开发时才需要的库和执行时需要的库分开管理。此时,我们需要把测试运行器和配置器工具写在 tests-require.txt 文件里,把执行时需要的库写在 requirements.txt 文件里。这种情况下,只要准备一个如 LIST 9.7 所示的 dev-requires.txt,就能通过一条 pip install -r dev-requires.txt 完成开发者环境的准备工作。

LIST 9.7 dev-requires.txt

-r requirements.txt
-r tests-require.txt

另外,建议将 --allow-external 和 --allow-unverified 等常用选项也一并写在 dev-requires.txt 中。这样可以将选项与 requirements.txt 分离,免得在使用 pip freeze > requirements.txt 自动生成文件时丢失选项。

9.2.3 requirements.txt 层级化

接下来,我们考虑对 requirements.txt 进行分割。首先,requirements.txt 是许多工具默认识别的文件名,所以这个文件名的重要性最高,要用来保存执行时所需程序库的列表。接下来考虑开发者使用的工具。这部分可以按用途分为测试工具、文档生成、模式迁移等多个类别。我们为每个用途分别准备一个文件。

LIST 9.8 ~ LIST 9.12 表示的就是一个文件分割的例子。

LIST 9.8 requirements.txt

pyramid==1.5.2 sqlalchemy==0.9.8 psycopg2==2.5.4

LIST 9.9 tests-require.txt

pytest==2.6.4 pytest-cov==1.8.1 coverage==3.7.1 webtest==2.0.6

LIST 9.10 docs-require.txt

Sphinx==1.3b2

LIST 9.11 db-requires.txt

alembic==0.6.7 psycopg2==2.5.4

LIST 9.12 dev-requires.txt

--no-index
-f http://devpi/+myproject/simple
-r requirements.txt
-r tests-require.txt
-r docs-require.txt
-r db-requires.txt

这样设置下来之后,就不会在执行时安装一些没用的库了。同时,tests-require.txt 等还可以拿到其他项目之中重复利用。

9.2.4 为部署和 CI+tox 准备的 requiremests

前面我们学习过,用 pip 能够将依赖库以 wheel 格式保存在 wheelhouse 里。为方便将它们运用到 CI 和部署当中,我们要简化这些依赖库的安装流程。

用 pip 管理程序包的情况下,依赖库会记录在 requirements.txt 中。这里我们跟前面一样,在 requirements.txt 里只保存依赖库的列表。

然后,为了在搭建环境时只从 wheelhouse 获取这些库,我们像 LIST 9.13 这样编写 dev- requires.txt,将库的获取位置限定为 wheelhouse。

LIST 9.13 dev-requires.txt

-f wheelhoouse
--no-index
-r requirements.txt

有了这些文件之后,就可以用下述方法从 wheelhouse 进行安装了。

$ pip install -r dev-requires.txt

接下来,我们把它应用到我们在 8.4.1 节学习过的测试环境工具 tox 上。tox 可以在 virtualenv 中为每个测试环境搭建一个虚拟环境,如果能通过 wheel 格式给各个环境安装依赖库,那么必将提升搭建环境的效率。

tox 可以在 tox.ini 文件中指定安装到环境的库(LIST 9.14)。由于这部分是直接交给 pip 处理的,所以指定的东西不一定非要是库,还可以是 requirements.txt 等文件。

LIST 9.14 tox.ini

[testenv]
deps = -rdev-requires.txt

这样设置下来之后,计算机就会根据 dev-requires.txt 从本地的 wheelhouse 安装依赖库。这里有一点需要注意,tox 不会查看 dev-requires.txt、requirements.txt 这类文件的内容,所以如果我们对这些文件进行了编辑,需要手动执行带 --recreate 选项的 tox 命令。

$ tox --recreate

虽然难以避免上述这类麻烦,但对于某些需要频繁重置环境的 CI 工具而言,它仍是一个非常省时省力的方法。特别是使用 travis.ci 等对执行时间有限制的工具时,缩短搭建环境的时间显得十分重要。

9.2.5 通过 requirements.txt 指定库的版本

我们在用 pip freeze 生成的 requirements.txt 文件中指定了库的版本。通过 requirements.txt 指定版本的方法有很多种,这里我们学习直接指定版本的方法。对于程序库而言,即便只是修复 Bug,也可能导致其运行出现变化。因此,开发、测试、正式环境要保证使用同版本的库。CI 工具可以用 tox 的 --recreate 选项来严格按照 requirements.txt 中描述的库重新搭建环境。另外,想知道环境中是否安装了未包含在 requirements.txt 中的库时,可以通过 pip freeze 指定 requirements.txt 进行查看(LIST 9.15)。

LIST 9.15 查看是否安装了未包含在 requirements.txt 中的库

$ pip freeze -r requirements.txt

随着程序库版本不断更新,wheelhouse 内的文件会越积越多。我们可以通过下述方法将未包含在 requirements.txt 中的库转移到其他目录。

$ mv wheelhouse wheelhouse.old
$ pip wheel -r requirements.txt -f wheelhouse.old

对正式服务器而言,直接从当前活动环境中撤走程序库会带来很高的风险。这时就需要花些心思来规避风险了,比如在 virtualenv 上重新搭建一个环境,然后切换 nginx 等反向代理的连接。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文