Python虚拟环境的原理及使用详解


Posted in Python onJuly 02, 2019

Python的虚拟环境极大地方便了人们的生活。本指南先介绍虚拟环境的基础知识以及使用方法,然后再深入介绍虚拟环境背后的工作原理。

注意:本指南在macOS Mojave系统上使用最新版本的Python 3.7.x。

1. 为什么使用虚拟环境?

虚拟环境为一系列潜在问题提供简单的解决方案,尤其是在以下几个方面:

  1. 允许不同的项目使用不同版本的程序包,从而解决依赖性问题。例如,可以将Project A v2.7用于Project X,并将Package A v1.3用于Project Y。
  2. 通过捕获需求文件中的所有包依赖项,使项目自包含且可重现。
  3. 在没有管理员权限的主机上安装软件包。
  4. 只需要一个项目,无需在系统范围内安装软件包,就能保持全局site-packages /目录整洁。

听起来很方便,不是吗?开始构建更复杂的项目并与其他人协作时,虚拟环境的重要性会凸显出来。很多数据科学家也需要熟悉虚拟环境中与多语言相关的Conda环境。

可按照先后次序来使用!

2. 什么是虚拟环境?

到底什么是虚拟环境?

虚拟环境是用于依赖项管理和项目隔离的Python工具,允许Python站点包(第三方库)安装在本地特定项目的隔离目录中,而不是全局安装(即作为系统范围内的Python的一部分)。

这听起来不错,但到底什么是虚拟环境呢?虚拟环境只是一个包含三个重要组件的目录:

  1. 安装了第三方库的site-packages /文件夹。
  2. 系统上安装的Python可执行文件的symlink符号链接。
  3. 确保执行Python代码的脚本使用在给定虚拟环境中安装的Python解释器和站点包。

最后一点在于会发生一些意想不到的错误,稍后会讲这一点,但现在先看看在实际中如何实际使用虚拟环境。

3. 使用虚拟环境

(1) 创造虚拟环境

假设想要为正在处理的项目创建一个名为test-project/的虚拟环境,该项目具有以下目录树:

test-project/ 
├── data     
├── deliver      # Final analysis, code, & presentations 
├── develop      # Notebooks for exploratory analysis 
├── src        # Scripts & local project modules 
└── tests

需要执行venv模块,它是Python标准库的一部分。

% cd test-project/ 
% python3 -m venv venv/    # Creates an environment called venv/

注意:可使用不同的环境名称替换“venv/”。

瞧!虚拟环境诞生了。现在项目变成:

test-project/ 
├── data    
├── deliver   
├── develop   
├── src   
├── tests  
└── venv         # There it is!

提醒:虚拟环境本身就是一个目录。

唯一要做的事情是通过运行前面提到的脚本来“激活”环境。

% source venv/bin/activate       
(venv) %                # Fancy new command prompt

现在我们位于活动的虚拟环境中(由命令提示符指示,前缀为活动环境的名称)。

我们会像往常一样处理项目,确保项目与系统的其他部分完全隔离。在虚拟环境中,我们无法访问系统范围的站点包,并且无法在虚拟环境之外访问安装包。

完成项目工作时,可以通过以下代码退出环境:

(venv) % deactivate 
%                  # Old familiar command prompt

(2) 安装包

默认情况下,只在新环境中安装pip和setuptools。

(venv) % pip list          # Inside an active environmentPackage  Version 
---------- ------- 
pip    19.1.1 
setuptools 40.8.0

如果想要安装第三方库的特定版本,比如numpyv1.15.3,可像往常一样使用pip。

(venv) % pip install numpy==1.15.3 
(venv) % pip listPackage  Version 
---------- ------- 
numpy   1.15.3 
pip    19.1.1 
setuptools 40.8.0

现在可在脚本或活动的Python shell中导入numpy。例如,假设项目包含以下几行脚本tests / imports-test.py。

#!/usr/bin/env python3 
import numpy as np

直接从命令行运行这个脚本时,可得到:

(venv) % tests/imports-test.py      
(venv) %                 # Look, Ma, no errors!

成功。脚本导入numpy没有故障。

4. 管理环境

(1) 需求文件

使我们的工作成果可被他人重新使用的最简单方法是在项目的根目录(顶层目录)中加入一个需求文件。为此,需要运行pip freeze,以下列出已安装的第三方软件包及其版本号:

(venv) % pip freeze 
numpy==1.15.3

并将输出写入文件,我们称之为requirements.txt。

(venv) % pip freeze > requirements.txt

更新软件包或安装新软件包时,都可使用相同的命令重写需求文件。

现在,任何共享项目的人都可以使用requirements.txt文件,通过复制环境以在系统上运行项目。

(2) 复制环境

等等——究竟是怎么做到的?

想象一下,我们的队友Sara从团队的GitHub存储库中删除了测试项目。在她的系统上,项目的目录树如下所示:

test-project/ 
├── data     
├── deliver   
├── develop   
├── requirements.txt 
├── src  
└── tests

注意到有点不寻常的东西了吗?是的,没错!没有venv /文件夹。

我们已经将它从团队的GitHub存储库中删除,因为它的存在可能会引起麻烦。

这就是使用requirements.txt文件对复制项目代码至关重要的一个原因。

要在机器上运行测试项目,Sara需要做的就是在项目的根目录中创建一个虚拟环境:

Sara% cd test-project/ 
Sara% python3 -m venv venv/

并使用pip install -r requirements.txt将项目的依赖项安装在活动的虚拟环境中。

Sara% source venv/bin/activate 
(venv) Sara% pip install -r requirements.txt 
Collecting numpy==1.15.3 (from -r i (line 1)) 
Installing collected packages: numpy 
Successfully installed numpy-1.15.3

现在,Sara系统上的项目环境与我们的系统完全相同。很整洁,不是吗?

(3) 故障排除

可惜事情并不总是按计划进行,总会遇到一些问题。也许错误地更新了特定的站点包后发现自己处于Dependency Hell的第九级,无法运行单行项目代码。也许它没那么糟糕,可能你会发现自己竟处于第七级。

无论你发现自己处于何种程度,解决问题并再次看到希望的最简单方法是重新创建项目的虚拟环境。

% rm -r venv/              # Nukes the old environment 
% python3 -m venv venv/         # Makes a blank new one 
% pip install -r requirements.txt    # Re-installs

大功告成,多亏了requirements.txt文件,又恢复了正常。然而另一个原因是始终要在项目中列入需求文件。

5. 虚拟环境如何做到这一点?

想了解更多有关虚拟环境的信息吗?比如,活动环境如何使用正确的Python解释程序并如何找到合适的第三方库?

(1) echo $ PATH

这一切都归结为PATH的价值,它告诉shell使用什么Python实例以及在哪里寻找网站包。在基础shell中,PATH看起来或多或少是这样表现的。

% echo $PATH 
/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin

调用Python解释器或运行.py脚本时,shell会按顺序搜索PATH中列出的目录,直到遇到Python实例。要查看PATH首先找到的Python实例,请运行which python3。

% which python3 
/usr/local/bin/python3         # Your output may differ

通过站点模块(这是Python标准库的一部分)查找此Python实例查找站点包的位置也很容易。

% python3              # Activates a Python shell 
>>> import site            
>>> site.getsitepackages()     # Points to site-packages folder['/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages']

运行脚本venv / bin / activate修改PATH,以便shell在搜索系统的全局二进制文件之前搜索项目的本地二进制文件。

% cd ~/test-project/ 
% source venv/bin/activate 
(ven) % echo $PATH~/test-project/venv/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin

现在shell知道如何使用项目的本地Python实例:

(venv) % which python3 
~/test-project/venv/bin/python3

在哪里可以找到项目的本地站点包?

(venv) % python3 
>>> import site 
>>> site.getsitepackages()['~/test-project/venv/lib/python3.7/site-packages']  # Ka-ching

(2) 理智检查

还记得以前的tests / imports-test.py脚本吗?看起来是下面这样:

#!/usr/bin/env python3 
import numpy as np

我们能够在活动环境中运行此脚本,不出现任何问题,是因为环境中的Python实例能够访问项目的本地站点包。

如果运行从项目的虚拟环境外部而来的相同脚本会发生什么?

% tests/imports-test.py        # Look, no active environmentTraceback (most recent call last): 
 File "tests/imports-test.py", line 3, in <module> 
  import numpy as npModuleNotFoundError: No module named 'numpy'

是的,出现了一个错误,但我们应该这样做。如果我们不这样做,那就意味着我们能够从项目外部访问项目的本地站点包,从而破坏了拥有虚拟环境的整个目的。出现错误的事实证明我们的项目与系统的其他部分完全隔离。

(3) 环境的目录树

有一件事可以帮助整理所有这些信息,即清楚地了解环境目录树的外观。

test-project/venv/        # Our environment's root directory 
├── bin 
│  ├── activate              # Scripts to activate 
│  ├── activate.csh            # our project's 
│  ├── activate.fish           # virtual environment. 
│  ├── easy_install 
│  ├── easy_install-3.7 
│  ├── pip 
│  ├── pip3 
│  ├── pip3.7 
│  ├── python -> /usr/local/bin/python  # Symlinks to system-wide 
│  └── python3 -> python3.7        # Python instances. 
├── include 
├── lib 
│  └── python3.7 
│    └── site-packages       # Stores local site packages 
└── pyvenv.cfg

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
在Django中编写模版节点及注册标签的方法
Jul 20 Python
python登录并爬取淘宝信息代码示例
Dec 09 Python
Django中的Signal代码详解
Feb 05 Python
python实现教务管理系统
Mar 12 Python
python dataframe向下向上填充,fillna和ffill的方法
Nov 28 Python
对Python闭包与延迟绑定的方法详解
Jan 07 Python
Python测试模块doctest使用解析
Aug 10 Python
python 扩展print打印文件路径和当前时间信息的实例代码
Oct 11 Python
python 实现两个线程交替执行
May 02 Python
django haystack实现全文检索的示例代码
Jun 24 Python
python+requests实现接口测试的完整步骤
Oct 27 Python
python爬虫分布式获取数据的实例方法
Nov 26 Python
python输出电脑上所有的串口名的方法
Jul 02 #Python
如何更优雅地写python代码
Jul 02 #Python
Python pip替换为阿里源的方法步骤
Jul 02 #Python
python set内置函数的具体使用
Jul 02 #Python
ZABBIX3.2使用python脚本实现监控报表的方法
Jul 02 #Python
浅谈python 中类属性共享的问题
Jul 02 #Python
如何通过Python实现标签云算法
Jul 02 #Python
You might like
PHP获取当前页面完整URL的实现代码
2013/06/10 PHP
php ios推送(代码)
2013/07/01 PHP
PHP实现根据设备类型自动跳转相应页面的方法
2014/07/24 PHP
标准版Eclipse搭建PHP环境的详细步骤
2015/11/18 PHP
Jquery数独游戏解析(一)-页面布局
2010/11/05 Javascript
jQuery 在光标定位的地方插入文字的插件
2012/05/10 Javascript
一个JS函数搞定网页标题(title)闪动效果
2014/05/13 Javascript
使用typeof方法判断undefined类型
2014/09/09 Javascript
JavaScript中变量声明有var和没var的区别示例介绍
2014/09/15 Javascript
jquery调取json数据实现省市级联的方法
2015/01/29 Javascript
让JavaScript中setTimeout支持链式操作的方法
2015/06/19 Javascript
浅析Bootstrip的select控件绑定数据的问题
2016/05/10 Javascript
省市联动效果的简单实现代码(推荐)
2016/06/06 Javascript
Angularjs Ng_repeat中实现复选框选中并显示不同的样式方法
2018/09/12 Javascript
详解如何创建并发布一个 vue 组件
2018/11/08 Javascript
Vue 动态组件与 v-once 指令的实现
2019/02/12 Javascript
JavaScript实现指定数量的并发限制的示例代码
2020/03/10 Javascript
Vue移动端用淘宝弹性布局lib-flexible插件做适配的方法
2020/05/26 Javascript
Vue+Vant 图片上传加显示的案例
2020/11/03 Javascript
Python实现KNN邻近算法
2021/01/28 Python
Python统计单词出现的次数
2018/04/04 Python
Python subprocess模块功能与常见用法实例详解
2018/06/28 Python
Django框架中间件定义与使用方法案例分析
2019/11/28 Python
python matplotlib模块基本图形绘制方法小结【直线,曲线,直方图,饼图等】
2020/04/26 Python
python爬取豆瓣电影排行榜(requests)的示例代码
2021/02/18 Python
详解html5 canvas 微信海报分享(个人爬坑)
2018/01/12 HTML / CSS
世界上最好的足球商店:Unisport
2019/03/02 全球购物
节约用水倡议书
2014/04/16 职场文书
计算机应用应届生求职信
2014/07/12 职场文书
环保公益策划方案
2014/08/15 职场文书
竞选大队干部演讲稿
2014/09/11 职场文书
工作保证书
2015/01/17 职场文书
助学金感谢信
2015/01/20 职场文书
团员自我评价范文
2015/03/10 职场文书
地道战观后感300字
2015/06/04 职场文书
python通过新建环境安装tfx的问题
2022/05/20 Python