返回介绍

3.2 环境与工具

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

本节,我们将对 Python 项目开发的必备工具进行了解。此外,还将学习项目的目录结构、必备程序包的管理方法以及安装方法。

3.2.1 用 virtualenv 搭建独立环境

如果大量项目全都混杂在一个环境下,程序很可能会在预想不到的地方停止运行,而且不利于我们把握当前环境的具体状态。所以为了防止出现这些恼人的情况,我们建议各位搭建简单的独立环境。

使用 virtualenv 可以给每个项目搭建一个独立的 Python 环境。

独立环境有以下优点。

· 添加程序包以及变更版本时,能将影响控制在当前环境内

· 便于判断已安装的程序包是否可以删除

· 不再需要该环境时,可以直接删除整个环境

· 一旦出了问题,那么问题必然出在该环境的项目上,这就有助于我们找出问题所在

◉ virtualenv

NOTE

当前介绍的版本为 virtualenv 1.11.6。

用 pip 安装外部程序库时,该库会被安装到 Python 的安装目录下。比如 Python 是安装在了 /usr/local/ 目录下,那么该外部程序库就会被安装在 /usr/local/lib/python2.7/site-packages 目录下,这就是库的默认安装路径。但这样一来,不同目的的程序库就全都安装到了同一目录下,不但容易导致版本冲突,而且很难分辨出哪些程序库已经没用了。

另外,在 /usr/local/ 下安装东西时,需要我们提供该目录的写入权限。我们对自己的计算机中的 OS 目录具有写入权限,但是不一定对其他计算机的 OS 目录也拥有写入权限。就算有,乱用权限也很容易导致意外事故,因此应尽量避免乱用权限。

其实,这些问题都可以用 virtualenv 解决。

virtualenv 的主要特征体现在下列功能上。

· 在 virtualenv 环境中可自由安装 Python,不需要提供 OS 管理员权限

· 在 virtualenv 环境下,可根据目的不同来安装程序库,这样一来包的安装目的和依存关系就会更加明确

· 仍然使用 Python 主体,且虚拟环境仅由一小部分备份文件构成,因此环境搭建速度快,占用硬盘空间小

· 无视 Python 主体的 site-packages,而且能分离主体上已安装完毕的程序包

· 可以用 activate/deactivate 命令随时启动 / 关闭 virtualenv 环境

virtualenv 命令可以将任意目录设置为“virtualenv 环境(Python 虚拟环境)”。激活 virtualenv 环境之后,Python 解释器会将该目录识别为默认安装目录。所以,如果我们此时用 pip 命令安装程序库,那么这个程序库将被安装到 virtualenv 环境中。

下面我们来了解一下 virtualenv 的一般使用方法以及一些常用选项。其他详细知识请参考以下网站。

Reference Guide - virtualenv 1.11.6 documentation

https://virtualenv.pypa.io/en/latest/

专栏 Python 标配的用户站点目录功能与 virtualenv 的差异

用户站点目录功能由PEP 3701 提出,随后被 Python 采纳并从 Python 2.6 版本开始提供。这个功能让 Python 解释器能够识别安装在用户目录 $HOME/.local 下的程序库。与此同时,pip 也纳入了这一机制,允许用户使用 --user 选项将程序库安装到 $HOME/.local 目录下。

有了这个功能之后,用户不必使用 virtualenv 就能自由地安装程序库。不过,用户站点目录功能无法像 virtualenv 一样搭建多个环境,自然也就不能在多个环境中切换。

1 https://www.python.org/dev/peps/pep-0370

◉ virtualenv 的使用方法

接下来我们看一看 virtualenv 的安装、virtualenv 环境的搭建以及启动(LIST 3.1、LIST3.2)。

LIST 3.1 安装 virtualenv

$ sudo pip install virtualenv

LIST 3.2 virtualenv 环境的搭建及启动

$ cd /home/bpbook/work
$ virtualenv venv
$ ls -F
venv/
$ source venv/bin/activate
(venv)$

如上所示,使用某一 virtualenv 环境的 activate 命令后,该 virtualenv 环境就会被设置为默认的 Python 执行环境。这里我们搭建了名为 venv 的 virtualenv 环境,因此命令提示符前会出现环境名 (venv) 。

执行 activate 后,PATH、PROMPT 等数个环境变量会被改写。这样一来,对象 virtualenv 环境的 bin 目录将在 PATH 搜索中被优先处理。此时,只有环境变量会被修改,文件并不会有任何变动。

在这个状态下,计算机会优先使用 venv/bin 目录下的执行文件来执行各个命令。给 virtualenv 环境安装额外的程序库时,我们需要如 LIST 3.3 所示,在命令提示符前有“(venv) ”的状态下执行 pip 命令。

LIST 3.3 给 virtualenv 环境安装程序库

(venv)$ pip install requests bottle
(venv)$ pip freeze
bottle==0.12.7
requests==2.4.3

如果要使用这个 virtualenv 环境的 Python,则要执行该 virtualenv 环境的 python 命令(LIST 3.4)。

LIST 3.4 运行 virtualenv 环境的 Python

(venv)$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56) [GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.executable
'/home/bpbook/work/venv/bin/python'
>>> import requests
>>> import bottle

解除 activate 时,需要还原之前被 activate 更改的环境变量。因此我们要结束 shell,或者执行 deactivate 命令(LIST 3.5)。

LIST 3.5 通过 deactivate 命令关闭 virtualenv 环境

(venv)$ deactivate
$ python -c "import sys; print sys.executable"
/usr/local/bin/python

virtualenv 环境的数量没有上限。这里我们再来搭建一个名为 another-venv 的 virtualenv 环境(LIST 3.6)。

LIST 3.6 搭建另一个 virtualenv 环境

$ virtualenv another-venv
$ ls -F
another-venv/   venv/

使用 another-venv 环境的 Python 时,我们无法 import 其他 virtualenv 环境安装的库。

LIST 3.7 运行另一个 virtualenv 环境的 Python

$ source another-venv/bin/activate
(another-venv)$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56) [GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.executable
'/home/bpbook/work/another-venv/bin/python'
>>> import requests
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'requests'

可见,每一个 virtualenv 环境都是相互独立运行的 Python 环境(LIST 3.7)。而且每个环境都仅由 Python 的一部分文件构成,所以能够很快搭建完成或者删掉,并不会占用太多硬盘空间。

专栏 virtualenv 环境的硬盘使用量

在 Ubuntu 14.04 下,Python 主体的硬盘使用量大约为 100 MB,每个 virtualenv 环境的硬盘使用量约为 6 MB。不过,如果使用了我们后面即将了解的 --always-copy 选项,那么每个 virtualenv 环境将占用约 50 MB。

不再使用的 virtualenv 环境可以连同其所在目录一起删除(LIST 3.8)。

LIST 3.8 删除 virtualenv 环境

(another-venv)$ deactivate
$ rm -R another-venv

专栏 在不 activate 的状态下执行 virtualenv 环境的命令

我们执行 activate 命令启动 virtualenv 环境时,环境变量会被更新,此后执行命令时会优先使用 venv/bin/ 目录下的文件。实际上,即便是在没有执行 activate 命令的状态下,只要我们用完整路径执行了 venv/bin/ 下的命令,就可以运行 virtualenv 环境中的程序。

$ python -c "import sys; print sys.executable"
/usr/local/bin/python
    
$ venv/bin/python -c "import sys; print sys.executable"
/home/bpbook/work/venv/bin/python
    
$ venv/bin/python
    
>>> import requests      # 可以从venv环境中导入
    
$ venv/bin/pip install flask   # 安装到venv环境中
...

因此,当我们想有计划地执行 venv 环境的程序,或者想启动服务器时,只要用完整路径指定 venv 环境的程序,就可以在不执行 activate 命令的状态下完成运行了。

◉ virtualenv 的选项

virtualenv 为用户提供了许多可用选项。我们可以通过 virtualenv --help 来查看选项列表。现在我们选其中一些比较好用的选项来了解一下。

· -p、--python

指定virtualenv环境下使用的Python,格式如--python=/usr/local/bin/python2.7 。

如果省略该选项,则默认选择执行virtualenv命令的Python。

· --system-site-packages

使用当前Python主体上已经安装的程序库。如果省略该选项,则默认忽略Python主体上已经安装的程序库。

· --always-copy

无论符号链接是否可用,一概不使用符号链接,而是直接复制文件。即便是允许使用符号链接的OS,在某些文件系统下仍会出现符号链接不可用的情况。此时就可以用到这个选项。

· --clear

删除指定的virtualenv环境中安装的依赖库等,初始化环境。

· -q、-quiet

执行virtualenv命令时,控制向工作台输出的信息量。

· -v、-verbose

执行virtualenv命令时,增加向工作台输出的信息量。

LIST 3.9 virtualenv 的选项示例

$ virtualenv -q --system-site-packages -p /usr/local/bin/python2.7 venv

如果我们经常用到某些选项,可以事先将其写入设置文件。这样一来,我们就不用每次执行命令时都再写一遍了。

在 Linux 系统下,设置文件默认使用 $HOME/.virtualenv/virtualenv.ini。举个例子,如果要在 virtualenv.ini 中指定 LIST 3.9 里的选项,我们可以按照 LIST 3.10 进行描述。

LIST 3.10 virtualenv.ini

[virtualenv]
python = /usr/local/bin/python2.7
quiet = true
system-site-packages = true

另外,还可以在环境变量中指定选项。如果我们同时用环境变量和设置文件指定了某个选项,那么将以环境变量的指定为准。当然,命令行传值参数的指定优先于一切。

环境变量名是根据选项名自动生成的。将选项名的“-- ”后的字母全改为大写,短线改为下划线,然后在开头加上 VIRTUALENV_ ,就是该选项所对应的环境变量。请各位在设置环境变量时记住这个规律。

● 示例

--quiet         -> VIRTUALENV_QUIET=true
--python        -> VIRTUALENV_PYTHON=/usr/local/bin/python2.7
--system-site-packages  -> VIRTUALENV_SYSTEM_SITE_PACKAGES=true

专栏 --system-site-packages 选项

virtualenv 环境不会引用 Python 主体上安装的程序包,也就是 /usr/local/lib/python2.7/sitepackages 目录下的程序包。因此,当我们新建了一个 virtualenv 环境时,这个环境处于干净的初始状态,没有安装任何多余的包。

相反地,如果我们想在 virtualenv 环境中使用 Python 主体上安装的程序包,那么在新建环境时可以加上 --system-site-packages 选项。

不过,一旦加上这个选项,我们就相当于同时使用两个环境,因此很难分辨出程序包在哪里,以及正在使用的是哪个程序包。这会导致 virtualenv 环境的优势大打折扣。所以,除非迫不得已,建议各位尽量不要使用 --system-site-packages 选项。

3.2.2 用 pip 安装程序包

NOTE

我们使用的是 pip 1.5.6。

给 virtualenv 环境额外安装程序包时,需要用该环境的 pip 命令。

pip 是用来安装程序包的命令。既可以经由网络进行安装,也可以直接从本地的程序包文件进行安装。第三方的程序库发布在 PyPI 上。pip 命令会默认从 PyPI 上搜索并安装程序包。

pip 提供了多个子命令。下面便是其子命令列表。

install

安装程序包(指定包名、包文件名、URL 等)

uninstall

卸载程序包

freeze

以 requirements 格式列表输出当前已安装的程序包及其版本

list

列表显示当前已安装的程序包

show

列表显示当前已安装程序包的版本信息

search

按指定关键字在 PyPI 上搜索程序包并显示结果列表

wheel

根据指定 requirement 构建 wheel 文件

help

显示帮助

接下来,我们将对 pip 的选项以及安装、卸载方法进行学习。其他详细内容请参考以下网站。

Reference Guide - pip 1.5.6 documentation

https://pip.pypa.io/en/latest/reference/index.html

User Guide - pip 1.5.6 documentation

https://pip.pypa.io/en/latest/user_guide.html#configuration

◉ pip 的选项

pip 的选项有两种,一种是不依赖于子命令的共通选项,另一种是指定给子命令的选项。比如 --quiet 和 --proxy 就是所有命令共通的选项,而 install 子命令则拥有 --upgrade 等自己独有的选项(LIST 3.11)。

这两种选项都需要在执行时通过命令行指定。

LIST 3.11 pip 的选项示例

$ pip --quiet --proxy=server:9999 install --upgrade requests

常用的选项可以事先写在设置文件中。这样可以省去每次都写的麻烦。

Linux 的默认设置文件为 $HOME/.pip/pip.conf。比如我们要在 pip.conf 中指定 LIST 3.11 pip 的选项示例中的选项,则可以按照 LIST 3.12 进行描述。

LIST 3.12 pip.conf

[global]
quiet = true
proxy = server:9999
[install]
upgrade = true

NOTE

上述内容只是个例子,并非推荐设置。各位请严格按照自己的需要设置各个选项。

另外,还可以在环境变量中指定选项。如果我们同时用环境变量和设置文件指定了某个选项,那么将以环境变量的指定为准。当然,命令行传值参数的指定优先于一切。

环境变量名是根据选项名自动生成的。将选项名的“-- ”后的字母全改为大写,短线改为下划线,然后在开头加上 PIP_ ,就是该选项所对应的环境变量。请各位在设置环境变量时记住这个规律。

● 示例

--quiet  -> PIP_QUIET=true
--proxy  -> PIP_PROXY=server:9999
--upgrade  -> PIP_UPGRADE=true

专栏 关于指定HTTP 代理

pip 需要使用 HTTP 协议从外部网站获取程序包。在某些企业或环境下,我们需要经由代理才能访问到外部网站。而且有些时候,我们必须输入 ID 和密码才可以使用代理访问外部网站(认证代理)。

在这类环境下使用 pip 时,我们要用 --proxy 选项指定代理,格式为 [user:passwd@]proxy.server:port (LIST 3.13、LIST 3.14)。

LIST 3.13 指定 pip 的代理

$ pip --proxy=proxy.example.com:1234 install requests

LIST 3.14 指定 pip 的认证代理

$ pip --proxy=beproud:passwd@proxy.example.com:1234 install requests

我们也可以像 LIST 3.15 这样,在设置文件或环境变量中指定 --proxy 选项。

LIST 3.15 在 PIP_PROXY 环境变量中指定

$ export PIP_PROXY=proxy.example.com:1234
$ pip install requests

除 PIP_PROXY 环境变量外,我们还可以在 HTTP_PROXY 环境变量中指定 Proxy(LIST 3.16)。

LIST 3.16 在 HTTP_PROXY 环境变量中指定

$ export HTTP_PROXY=proxy.example.com:1234
$ pip install requests

◉ 安装程序包

pip install 是安装程序包的命令。install 子命令可以详细指定“安装什么”“从哪里安装”“如何安装”。因此,我们在看帮助文档时会发现它有很多选项和对象指定方法(LIST 3.17)。

LIST 3.17 pip install 的帮助

$ pip install -h
Usage:
  pip install [options] <requirement specifier> ...
  pip install [options] -r <requirements file> ...
  pip install [options] [-e] <vcs project url> ...
  pip install [options] [-e] <local project path> ...
  pip install [options] <archive url/path> ...
...

从 PyPI 安装程序包的方法如 LIST 3.18 所示。这里,我们可以指定一个或多个程序包。

LIST 3.18 从 PyPI 安装

$ pip install requests
$ pip install flask bottle

如果手边有源码,还可以像 LIST 3.19 这样进行安装。

LIST 3.19 从源码包安装

$ pip install ./logfilter-0.9.2

像上例这样从本地目录安装时,我们需要写明本地路径,如 ./logfilter-0.9.2 或 file://logfilter-0.9.2 等。如果只写 pip install logfilter-0.9.2 ,计算机会跑到 PyPI 上去找名为 logfilter-0.9.2 的程序包。

从源码安装时,我们可以使用 -e(--editable)选项。这样一来,安装时不会复制源码,而是直接在该目录下原地进行安装。对于一些尚在开发中的源码,用 editable 进行安装可以省去每次修改代码后重新安装的麻烦(LIST 3.20)。由于程序可以在运行时直接使用我们编辑过的代码,所以 editable 也被称为可编辑安装。

LIST 3.20 指定 editable 安装源码目录

$ pip install -e ./logfilter-0.9.2

将版本库 clone 下来并进行安装时,需要在版本库的 URL 前添加例如 hg+ 等版本库类别,然后再执行 pip install (LIST 3.21)。在执行本例的过程中,需要在内部使用 hg 命令,因此必须有一个可以使用 hg 命令的环境。对象为 git 版本库时请将上述 hg 替换为 git 。

现在让我们来执行安装。

LIST 3.21 从 hg 上 clone 并安装

$ pip install hg+https://bitbucket.org/shimizukawa/logfilter

如果想在 clone 来的源码上进行开发,我们可以同时加上 -e 选项。此时需要如 LIST 3.22 所示,在 URL 末尾添加 #egg=<< 程序包名 >> 。

LIST 3.22 从 hg 上 clone 并 editable 安装

$ pip install -e hg+https://bitbucket.org/shimizukawa/logfilter#egg=logfilter

如果要一次安装多个程序包,比较简便的方法就是使用对象程序包以及描述这些程序包的 requirements 格式的文件。文件名一般使用 requirements.txt。我们可以自己动手准备这个文件,不过一般我们都会用 pip freeze 来输出。requirements.txt 文件用 -r(--requirement)选项指定(LIST 3.23)。

LIST 3.23 通过 requirements.txt 安装

$ pip install -r requirements.txt

使用 pip 时,如果之前已经安装过指定的程序包,计算机并不会自动将其更新为新版本。指定更新到某一版本需要用 -U(--upgrade)选项(LIST 3.24)。

LIST 3.24 用 -U 选项更新版本

$ pip install -U requests

如果不想每次都从 PyPI 下载程序包,我们可以用 --download-cache 选项指定缓存目录(LIST 3.25)。此时,为了检查版本,计算机仍会进行网络通信。如果缓存目录中有我们要用的版本,计算机则会直接用缓存文件进行安装。

LIST 3.25 指定下载缓存

$ pip install --download-cache=~/.pip-cache requests

如果想一直使用缓存目录,建议各位在环境变量中设置该选项(LIST 3.26)。只要维持环境变量中的这一设置,我们就能有效运用缓存。

LIST 3.26 在环境变量中设置下载缓存

$ export PIP_DOWNLOAD_CACHE=~/.pip-cache
$ pip install requests

NOTE

从 pip-6.0 起,下载缓存改为默认有效。指定 --download-cache 选项时会出现无效警告。

◉ 记录程序包一览表

pip freeze 命令用来将已安装程序包及其版本的一览表以 requirements 格式输出。其执行如 LIST 3.27 所示。

LIST 3.27 pip freeze

$ pip freeze
Flask==0.10.1
Jinja2==2.7.3
MarkupSafe==0.23
Werkzeug==0.9.6
argparse==1.2.1
itsdangerous==0.24
wsgiref==0.1.2

NOTE

从 pip-6.0 起,不再显示 Python 标准库 argparse 和wsgiref。

pip freeze 以 requirements 格式输出程序包及其版本的列表。为了方便 pip install 使用这些内容,它们会被保存在 requirements.txt 文件中(LIST 3.28)。这个文件名并不是硬性要求,但大多数情况下我们习惯使用 requirements.txt。

LIST 3.28 将 pip freeze 的输出保存在 requirements.txt 中

$ pip freeze > requirements.txt

这样一来,我们就可以用类似 pip install -r requirements.txt 的方式在其他环境中安装相同版本的程序包了。

如果环境中安装的程序包发生变动,我们可以再次执行 pip freeze > requirements.txt ,以更新文件内容。此时,用 -r(--requirement)选项指定原来的 requirements.txt 可以确认更新前后的差别(LIST 3.29)。用这种方法能帮助我们确认是否存在意外更改。

LIST 3.29 pip freeze -r 的结果

$ pip install bottle
$ pip freeze -r requirements.txt
Flask==0.10.1
Jinja2==2.7.3
MarkupSafe==0.23
Werkzeug==0.9.6
argparse==1.2.1
itsdangerous==0.24
wsgiref==0.1.2
## The following requirements were added by pip --freeze:
bottle==0.12.7

专栏 在 requirements.txt 内指定版本库

如果我们在当前环境下用 -e(--editable)安装了版本库的代码,那么执行 pip freeze 后,输出结果如下。

$ pip install -e hg+https://bitbucket.org/shimizukawa/logfilter#egg=logfilter
$ pip freeze
-e hg+https://bitbucket.org/shimizukawa/logfilter@96fd26dae42053c015d3285c
002d45aa5fe6e324#egg=logfilter-dev
Flask==0.10.1
Jinja2==2.7.3
MarkupSafe==0.23
Werkzeug==0.9.6
itsdangerous==0.24
wsgiref==0.1.2

该版本库特定版本的代码会被安装到使用 requirements.txt 进行 pip install 时的环境中。所以各位请注意,安装时会执行版本库 clone 操作,而且无论版本库是否接到了新的提交,安装时都会使用我们指定的版本。

◉ 卸载程序包

pip uninstall 命令用于卸载、删除当前已安装的程序包。其执行方式如 LIST 3.30 所示。

LIST 3.30 pip uninstall

$ pip uninstall flask
Uninstalling flask:
  /home/bpbook/work/venv/lib/python2.7/site-packages/...
  ...
Proceed (y/n)? y
  Successfully uninstalled flask

屏幕上会显示待删除文件的列表,并向用户询问是否真的要删除。此时输入 y 并按下 Enter 键即可完成删除操作。

如果不需要确认,可以加上 -y(--yes)选项,其执行如 LIST 3.31 所示。

LIST 3.31 pip uninstall -y

$ pip uninstall -y flask

请注意,pip uninstall 命令只会卸载我们指定的程序包。比如安装 Flask 时会捆绑安装 Jinja2 等 4 个关联程序包,这些程序包在 Flask 被卸载之后仍会残留在环境中。如果我们不再需要这些程序包,就必须通过 pip uninstall 手动删除它们,或者直接重建 virtualenv 环境,选我们需要的程序包重新安装。

3.2.3 小结

开发 Python 项目时,我们可以用 virtualenv 搭建该项目专用的虚拟环境。有了这个环境,我们使用程序库时就不会影响到其他项目了。项目所需的程序库用 pip 进行安装。用 pip freeze 命令搭建某项目环境的 requirements.txt 文件之后,我们能够轻松重建该项目所需的环境。除此之外,部署等方面也有 pip 和 virtualenv 的用武之地。这两个工具是 Python 开发环境的基础,建议各位牢记它们的使用方法。

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

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

发布评论

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