Python进阶-第三方库管理和虚拟环境

本文为《爬着学Python》系列第十三篇文章。


Python能在这几年火起来,靠的不是网上一大片的爬虫和服务器后端知识的应用(本专题就是这样的,这么说真的好吗?不过我们总得认清事实是吧。),靠的是Python搭上了大数据和人工智能的风。而Python之所以能很好地适应人工智能方面的应用,不是因为该语言对这方面进行了优化,我认为主要的原因有以下两点:一个是简单易学,方便了数学、工程和金融等行业各领域的对新技术开放包容的人士入门;另一个是种类丰富而且文档详实的第三方库满足了不同的需求。前者让更多人加入到Python的行列中来,后者让Python快速实现功能的能力非常强大。

今天我们主要讲讲Python的第三方库的管理。这方面的例子有很多,比如刚才提到的数据处理机器学习,那么不得不提的是SciPy,NumPyscikit-learn想必很多人都不陌生。不过本专题不是为了学这个,本专题是借Python学习互联网相关知识,所以我们以request和flask为例(哇,突然感觉自己过时了,但是既然本来决定好了专题内容,现在也不临时改了。况且我也不会啊,#无奈。而且我也没精力同时更新两个专题啊,#摊手。)。

上面是废话,下面是正文。

pip

没错,首先声明,我们主要用pip来下载第三方库,实在特殊的环境才会使用easy_install。原因也很简单,virtualenv都开始自带pip了,我们跟着大佬养成习惯就好啦。

说了几句可能有新手还不知道pip到底是什么东西。简单来说就是Python的yum,好吧这可能是废话,操作过RedHat不会不知道pip。真正地简单来说,pip是一个用来便捷管理Python第三方库的命令行工具。由于前面提到过我们主要用Windows示例,我们就用PowerShell来演示。

如果说不知道PowerShell是什么,可以理解为新一代的cmd。如果是以Windows作为主力开发环境,建议把PowerShell固定在任务栏。想要了解PowerShell的更多知识,可以参考Getting Started with PowerShell 3.0 | Channel 9。其中一个主讲Jeffery Snover是PowerShell的主力开发工程师,是微软非常厉害的服务器架构和管理方面的大牛,在C9可以免费看到大牛手把手教你敲脚本,如果对英文不自信,该系列甚至还有中文字幕!

之所以如此介绍PowerShell,是因为它真的非常“powerful”,而且我们可以用PowerShell来熟悉Shell编程,熟悉脚本编写。说到底我们是来学习知识的,不要死盯着pip。如果进度许可,以后我可能会给一个PowerShell脚本爬虫实例(大概会吧)。是的,PowerShell的一些特性使得他原生地可以非常完美地实现静态网页的爬虫功能,甚至要比Python更优雅,你就说powerful不powerful。

好了言归正传,win+r打开运行命令,输入powershell即可打开命令行窗口。我们就可以直接使用pip命令来下载第三方库了。

如果提示没有该命令,先确保已经安装Python(开个玩笑),我们可以去设置环境变量。既然就在PowerShell,那么不妨就用它来设置好了(嫌麻烦可以直接我的电脑-右键属性-高级系统设置-高级-环境变量-用户变量-Path-加上Python文件夹和scripts文件夹或bin文件夹)。查看所有本地环境变量可以直接查看虚拟驱动器,查看具体的环境变量可以查看全局变量:

PS C:\> ls env:

Name                          Value
----                          -----
ALLUSERSPROFILE               C:\ProgramData
APPDATA                       C:\Users\somarl\AppData\Roaming
...//其他就省略了

或者

PS C:\> $env:path
I:\SecureCRT\;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client
\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPower
Shell\v1.0\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Fi
les\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R)
Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine C
omponents\IPT;C:\Program Files\Calibre2\;I:\Git\cmd;I:\mysql-5.7.18-winx64\bin;...//还有一大串就省略了

添加环境变量也很简单

PS C:\> $Env:path=$Env:Path+";I:\Anaconda3\Scripts;I:\Anaconda3\Scripts"  

这里只是我的示例,PowerShell不是我们要介绍的重点,这几句命令非常简单,没有用到pipeline,很容易理解。

总之只要在命令行中输入pip回车能够进入库管理工具就可以了。

virtualenv

安装

我们就用虚拟环境工具包作为外部库的第一个示例。使用pip安装外部库非常简单,只要输入

pip install virtualenv

或者某些情况下(比如有些Linux不同的设置下)会需要输入

pip3 install virtualenv

如果没有安装过,那么pip就会自动寻找适配的版本开始下载安装。这里面存在以下几个问题:

  • 找不到适配的版本怎么办
  • 下载速度太慢怎么办
  • 安装失败怎么办

首先适配的版本找不到的话,有可能是平台(Windows/Linux/Unix)的原因,也有可能是数位的原因(32/64),也有可能是Python版本的原因(2.4/2.7/3.2/3.5)。这种错误不会指出到底是哪个不适配,具体可以去PyPI查看,PyPI是Python官方的库索引,我主要用来查看各种库的兼容信息。

下载速度太慢可以换国内的镜像。这个在后面介绍conda的时候会再介绍。我们可以临时在命令行后面加上参数

pip install virtualenv -i https://pypi.tuna.tsinghua.edu.cn/simple

这是清华的镜像,我自己用的是豆瓣的镜像,好像阿里也有镜像,这些百度一下就可以看到。Linux习惯了改各种配置文件,但是Windows总觉得有些不舒服。conda会有比较人性化的命令行直接设置永久的镜像。

安装失败的话,一般会有报错信息,可以根据报错信息处理。一般来说Windows平台常见的报错是CPython库的C依赖相关问题报错,Linux平台常见的报错是权限不足的问题。后者比较好解决,直接在命令前面加上sudo就可以了。

CPython的问题有以下几种解决办法:

  • PyPI或者Github找找看有没有类似的纯Python库。这么做其实不太推荐,但是这么做也有好处,就是如果完全不用CPython包可以用PyPy加速。
  • LFD找找看有没有编译好的wheel文件,全称叫Python Extension Packages for Windows,这是比较推荐的解决方案。关于wheel文件的使用方法下面会讲到。
  • 去库的Github地址找官方的针对Windows的编译好的文件(不一定有,一般是没有的),或者自己编译(不推荐,我以前做过这种事,体验很差)。
  • 安装支持环境,这个看上去最理所当然的方法反而是我不太喜欢的。原因在于VS有些臃肿,我还是喜欢用VS6.0。

关于wheel文件的使用,其实很简单,就是pip安装的时候不要指出安装包的名字,直接给出wheel文件的地址就可以了。比如:

pip install G:\action\tmp\Twisted‑17.9.0‑cp36‑cp36m‑win_amd64.whl

大概是这样吧,很久没用过,应该是这样的。如果失败了,试试先pip install wheel

OK,那么就算讲完了怎么用pip安装扩展包了。

卸载、更新、查看

和安装对应,卸载只需要输入

pip uninstall virtualenv

非常合理的做法。至于更新,其实为了程序的稳定运行和兼容性,这个功能其实是不常用的,这也是pip默认你想要更新的话其实就和直接重新安装没区别,这个逻辑我觉得设计也算巧妙(conda有update功能,pip没有)。

至于你如果要批量更新,去StackOverflow或者百度找会有很多脚本,或者Anaconda控制台,Pycharm都有相应的功能可以实现。当然,我并不推荐做这种事情。这也是我们会需要虚拟环境的原因,库文件稳定性是首要考虑的问题,所以更新要慎重。我的意思也不是不建议各位更新,只是不建议批量更新带来不必要的麻烦。

查看库有两种,一种是查看安装了哪些库

pip list

一种是查看某个库的信息。

pip show virtualenv

list命令也有相关的参数,也可以写进配置文件中,这里不赘述了。show命令主要是用来看安装地址location,环境依赖requires,开源协议license,当然,有些有主页的可以找到一些文档。

关于pip的讲解到此为止,如此简单的工具讲了这么多废话了。还有一些功能没讲呢,会穿插在virtualenv和conda中讲。

virtualenv的用法

我们讲了这么久我们需要虚拟环境,那么virtuaenv是什么,到底怎么用呢。

virtualenv是一个虚拟环境工具,用来构建一个Python程序运行的特殊环境。之所以需要特殊的环境,是为了方便移植,比如你可以让别人轻松地还原你的源程序运行的环境。同时它也方便的环境测试与管理,比如我们可以测试在不同的Python版本不同的外部库版本下程序的表现,就可以用虚拟环境来做到,而不必在电脑上安装多个版本Python,避免互相冲突。

具体的各种参数我就不讲了,virtualenv可以指定Python版本,可以指定包括哪些库。我们默认就是用virtualenv来运行我们主要Python版本,主要是为了管理外部库环境复制和还原,因此我们使用最简单的命令就可以了(Python版本的切换我倾向于用Conda,后面会讲到,比较彻底)。

PS G:\action\pipl> virtualenv venv

如果安装了virtualenv,那么直接进入项目根目录输入virtualenv venv就会创建一个目前Python版本的虚拟环境。其中venv是这个环境的名字,一般都叫这个。

在比较新的版本virtualenv中,这种默认创建方式会自动安装pipsetuptoolswheel三件套,你也可以通过如--no-pip的参数来防止安装这些包。

最简单的创建方式是有它的道理的,因为这是最常见的应用场景,绝大多数情况下确实是virtualenv venv就能解决问题了。创建完成后目录下会多出一个虚拟环境为名字的文件夹。

进入虚拟环境

创建完成后我们需要进入虚拟环境,否则命令行怎么知道你到底想在哪个环境执行命令呢。激活的方式很简单

PS G:\action\pipl> venv\Scripts\activate

如果出现权限问题或者安全问题。用管理员运行的PowerShell也是无济于事的,直接将出错信息百度,会有更改安全策略的解决方式。如果是Linux环境,注意source要把Scripts改成bin,值得一提的是Windows环境下激活虚拟环境会卡住几秒,Linux几乎是秒进。成功进入后,命令行会有虚拟环境的前缀。

这时我们再进行一些动作,都是虚拟环境下了,比如说我们进入Python试试引入一些安装过的外部库。

在外部环境中我肯定是安装了requests的,这怎么说也算是爬虫的最关键的库了。我们不妨试试刚学的列出安装过的Python库。

可以看到除了三件套确实什么都没有。我们可以试试安装外部库

可以看到确实可以安装。

一下子多了许多库出来。

退出虚拟环境

这个很简单,只要在虚拟环境中输入deactivate就能退出。

环境还原

现在我们来讲刚才提到的,关于环境还原的问题。如果我在开发中用到了一些依赖环境,那么我该如何让别人知道我用了哪些库呢?是不是对着代码一个个去找import了哪些库?这样做不仅麻烦而且容易遗漏,文件一多就会是很糟糕的体验了。

换个思路,我们只要让别人知道用pip安装过哪些库就可以了。我们可以用pipeline把powershell的pip list屏幕输出保存到文件中。但是还有更简单的方法,pip内置了这样方法。

(venv) PS G:\action\pipl> pip freeze >requirements.txt

这样项目根目录下会多出一个需求文件。打开来看一下。

可以看到除了三件套以外的包都在里面了。使用pip生成需求文件还有一个好处,就是可以用pip快速还原环境。比如我们再新建一个虚拟环境,并且还原刚才的环境(注意要把requirements.txt放在新项目的根目录下)。

PS C:\Users\somarl> cd G:\action\pipm
PS G:\action\pipm> virtualenv venv
Using base prefix 'I:\\Anaconda3'
New python executable in G:\action\pipm\venv\Scripts\python.exe
copying I:\Anaconda3\python.exe => G:\action\pipm\venv\Scripts\python.exe
Installing setuptools, pip, wheel...done.
PS G:\action\pipm> cp G:\action\pipl\requirements.txt G:\action\pipm\requirements.txt
PS G:\action\pipm> venv\Scripts\activate
(venv) PS G:\action\pipm> pip install -r requirements.txt

在实际操作中,我们的项目一般是用git clone下来的,所以不会需要手动去找requirements.txt,而且一般虚拟环境会被gitignore掉。这也是为什么大家都用venv当作虚拟环境名字,是为了方便git的相关操作。当然,在上面的操作中我也可以不复制requirements.txt文件,直接在pip install -r中参数设置成之前的路径就可以,这里是为了还原一般的使用场景,而Git相关的知识我还没有讲过,所以目前先不管它。

当然这也不是一劳永逸的。我们可以看看还原了哪些库。

注意到Twisted不见了,这也是我拿它作示例的原因。这就是我们刚才说过的Windows环境下pip安装可能出错的地方。错误信息是这样的

error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Builds": http://landinghub.visualstudio.com/visual-cpp-build-tools

因此我们确实有的时候需要注意到这些问题。如果你用别人的自构爬虫框架,Twisted是出现率非常高的库。我们可能会需要手动安装这样的库。不仅爬虫,科学计算相关包中对CPython的依赖其实更明显,很多库需要手动安装。或者你可以使用Linux,当然如果这种程度的问题都有很大的困扰,那么Linux系统给你带来的困扰可能会更多,对计算机原理和操作系统不是特别了解的不太推荐使用Linux。

Conda

除了virtualenv以外,我们提到虚拟环境,我比较推荐的还有Conda。在我看来Conda其实更适合本地环境的构建而不是虚拟环境的构建,我个人是把Conda当作增强版的pip来使用的。

Conda强在不仅可以改变环境的包,甚至可以改变环境本身。比如说我的电脑装的是Python3.6,但是后来我发现我其实比较喜欢Python3.5怎么办呢。我不必每次创建一个虚拟环境,我不必卸载Python3.6重新安装一个Python3.5,我不必更改各种软链(Linux)。Conda可以把默认的Python运行环境改掉。

所以说,如果说pip是管理Python库的,那么Conda可以说是用来管理Python的(它本身也可以管理库,而且比pip更强,只是包的数量不及pip多)。至少我目前是这么用的。而且其实熟悉Linux的同学可能知道,Conda不仅仅适用于Python,它的适应面还能更广。

Conda和pip以及virtualenv的关系,就好比Tornado和Django以及uWSGI甚至Nginx的关系。它是一种类似的交叉包容但又有所侧重的关系。

所以Conda是非常全能的工具。它可以做到pip能做到的事情,它可以做到virtualenv能做到的事情,它还可以做到这两个工具做不到的其他的事情。可惜的事实是Tornado不仅功能上无所不能、性能也强劲得让人刮目相看,但却依然没有Django受欢迎,也不如Flask,几乎可以说和Bottle、web2py一样是被冷落的那类框架。

不过好在Conda还是非常受欢迎的。因为它不仅功能强,它的虚拟环境其实比virtualenv更加纯粹。它的Python包管理依赖追踪能力是pip望尘莫及的。但是出于习惯,现在主流的虚拟环境工具是virtualenv,主流的库管理工具是pip,这两个也是我今天介绍的重点。但我还是要推荐一下Conda,它好到值得你去使用。

具体的使用技巧,本文就不再介绍了,篇幅有限是一方面,另一方面我自己对Conda的使用也算不上理解多深,就不献丑了。有兴趣的不妨去探索吧。

另外再提一下Python3.3以上版本其实是有自带的虚拟环境工具的,直接就叫作venv,用它创建环境的方式是这样的

python -m venv venv

要注意后面的那个venv是虚拟环境的名字,前面的那个是工具的名字。有趣的是它的体积小但性能其实也很强。使用方法和virtualenv大同小异,这里也不展开讲了。

最后讲些废话

之前说好了在Conda相关内容中讲怎么用命令行永久改镜像,结果后来还是忘了。其实很简单,Conda有config方法直接加参数--add channels 地址就行了。这样就能避免在Windows系统中编辑配置文件的违和感了。我Conda用的是清华的镜像,地址百度一下应该就有。

这篇还是以介绍pip和virtualenv为主,我能想到的大部分场景都尽量进行了说明,如果有缺漏的地方可以直接留言提出来。

链接

  1. Getting Started with PowerShell 3.0 | Channel 9
  2. PyPI- the Python Package Index
  3. Conda:误解与迷思

推荐阅读更多精彩内容