- 引言
- 本书涉及的内容
- 第 1 部分 Python 开发入门
- 第 1 章 Python 入门
- 第 2 章 开发 Web 应用
- 第 3 章 Python 项目的结构与包的创建
- 第 4 章 面向团队开发的工具
- 第 5 章 项目管理与审查
- 第 6 章 用 Mercurial 管理源码
- 第 7 章 完备文档的基础
- 第 8 章 模块分割设计与单元测试
- 第 9 章 Python 封装及其运用
- 第 10 章 用 Jenkins 持续集成
- 第 11 章 环境搭建与部署的自动化
- 第 12 章 应用的性能改善
- 第 13 章 让测试为我们服务
- 第 14 章 轻松使用 Django
- 第 15 章 方便好用的 Python 模块
- 附录 A VirtualBox 的设置
- 附录 B OS(Ubuntu)的设置
9.2 巧用程序包
在需要多次重复安装的时候,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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论