0
点赞
收藏
分享

微信扫一扫

选择哪种工具

不存在适用于所有情况的最佳解决方案。一家公司认为好的解决方案可能并不适用于

其他团队的工作流程。而且每个应用的需求也各不相同。小项目可以只使用 virtualenv

或 venv,比较简单,但大型项目可能还需要 buildout 的帮助,以便进行更复杂的装配。

之前没有详细说明的是,在 buildout 早期版本(2.0.0 版之前)中,可以在隔离环境中

对项目进行装配,其结果与 Virtualenv 给出的结果类似。不幸的是,这个项目的 1.x 分支不

再受到维护,所以不建议因为这个原因使用它。

我推荐尽可能使用 venv 模块,而不是 virtualenv。因此,对于面向 Python 3.4 或更高

版本的项目,应该默认选择 venv。在 Python 3.3 中使用 venv 可能不太方便,因为没有内


setuptools 和 pip 的支持。对于面向更多 Python 版本(包括其他解释器和 2.x 分支)

的项目,virtualenv 似乎是最佳选择。

系统级环境隔离

在大多数情况下,软件实现之所以可以快速迭代,是因为开发人员复用了大量现有组

件。不要重复你自己(Don't Repeat Yourself),这已经成为许多程序员的通用准则和座右铭。

将其他包和模块用在代码库中只是这种文化的一部分。二进制库、数据库、系统服务、第

三方 API 等也应该被当作“可复用组件”。甚至整个操作系统都是可复用的。

基于 Web 应用的后端服务是一个超级复杂的应用实例。最简单的软件栈(software

stack)通常由几层组成(从最底层开始):

• 数据库或其他类型的存储。

• Python 实现的应用程序代码。

• HTTP 服务器,例如 Apache 或 NGINX。

当然,这些软件可以进一步简化,但实际上是不可能的。事实上,大型应用往往复杂

到难以区分每一层。大型应用会用到多种不同的数据库,被分为多个独立进程,还会用到

许多其他系统服务来进行缓存、队列、记录日志、服务发现等等。遗憾的是,复杂度没有

上限,代码似乎只是遵循热力学第二定律而已。

真正重要的是,并非所有的软件栈元素都可以在 Python 运行环境的层面进行隔离。无

论是 HTTP 服务器(例如 NGINX)还是关系型数据库管理系统(RDBMS,例如 PostgreSQL),

在不同的系统上通常都有不同的版本。如果没有合适的工具,很难保证开发团队中每个人

使用的每个组件的版本完全相同。如果团队中所有开发人员都在开发同一个项目的话,那

么所有人可能会在开发工具箱上获得相同版本的服务,这在理论上是可能的。但如果他们

使用的操作系统与生产环境不同的话,所有这些努力都是徒劳的。当然也不可能强迫程序

员在并非本人最喜欢的系统上工作。

问题在于,可移植性仍然是一项巨大的挑战。在生产环境中,并非所有服务的运行方

式都和在开发人员电脑上完全相同,而且这一点不可能改变。即使是 Python 在跨平台方面

付出了巨大的努力,但在不同系统上的行为也会有所不同。通常来说,这些情况都有详细

的文档,只有直接进行系统调用时才会发生。但是,靠程序员的记忆力来记住一长串兼容

性问题,是很容易出错的。

这个问题的常见解决方法就是将整个系统隔离为应用程序环境。一般可以利用各种类

型的系统虚拟化工具来实现。当然,虚拟化会降低性能,但是现代计算机的硬件都支持虚

拟化,性能损失通常可以忽略不计。另一方面,可能的好处却有很多,如下所示。

• 开发环境可以完全匹配生产环境中使用的系统版本和服务,这有助于解决兼容性

问题。

• 系统配置工具(如 Puppet、Chef 或 Ansible,如果用的到的话)可以复用于开发环

境配置。

• 如果可以自动创建这样的环境,那么新来的团队成员就可以轻松上手项目。

• 开发人员可以直接调用系统底层特性,在工作机的操作系统上可能没有这些特性,举个

例子,在 Windows 中不可用的用户空间文件系统(File System in User Space,FSUS)。

使用 Vagrant 的虚拟开发环境

目前,Vagrant 似乎是最流行的工具,用一种简单方便的方法来创建并管理开发环境。

它可用于 Windows、Mac OS 和一些常见的 Linux 发行版,没有任何其他依赖。Vagrant 以

虚拟机或容器的形式来创建新的开发环境。具体实现取决于虚拟化供应商(provider)。

VirtualBox 是与 Vagrant 安装程序绑定的默认供应商,但也有其他供应商。最有名的供应商

是 VMware、Docker、LXC(Linux Containers)和 Hyper-V。

Vagrant 最重要的配置是一个名为 Vagrantfile 的文件。每个项目的这个文件都应该

是独立的。该文件中最重要的内容如下所示。

• 选择虚拟化供应商。

• 用作虚拟机镜像的 box 文件。

• 选择环境搭建(provisioning)方法。

• 虚拟机(VM)和虚拟机主机之间的共享存储。

• 虚拟机与主机之间的转发端口。

Vagrantfile 的语法语言是 Ruby。示例配置文件提供了用于启动项目的优秀模板,并

且还有详细的文档,因此无需掌握这种语言的知识。用一行命令就可以创建模板配置文件:

vagrant init

这一命令会在当前工作目录下创建一个名为 Vagrantfile 的新文件。通常最好将这

个文件保存在相关项目的根目录下。这个文件已经是一个有效配置,可以利用默认供应商

和基础镜像文件(base box)来创建新的虚拟机。默认不启用环境搭建(provisioning)。添

加完 Vagrantfile 后,利用下面这个命令可以启动新的虚拟机:

vagrant up

初始启动可能需要几分钟的时间,因为需要从网上下载 box 文件。还有一些初始化过

程可能要花费一些时间,这取决于使用的供应商、box 文件和每次打开现有虚拟机时的系

统性能。通常来说,这个过程只需要几秒。一旦启动并运行了新的 Vagrant 环境,开发者可以利用下面这个简短的命令连接 SSH:

vagrant ssh

在项目源代码树中,在 Vagrantfile 之下的任何位置都可以运行这一命令。为了方

便开发人员,我们会在上层目录中查找配置文件,并与相应的虚拟机实例进行匹配。然后

它会建立安全的 shell 连接,可以像任何普通远程机器一样与开发环境进行交互。唯一的区

别在于,整个项目的源代码树(根目录是 Vagrantfile 所在的位置)是在虚拟机文件系

统的/vagrant/目录下。

举报

相关推荐

0 条评论