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 相关文章推荐
python使用PyFetion来发送短信的例子
Apr 22 Python
Python操作串口的方法
Jun 17 Python
Python实现的redis分布式锁功能示例
May 29 Python
浅析python继承与多重继承
Sep 13 Python
python 随机打乱 图片和对应的标签方法
Dec 14 Python
python try 异常处理(史上最全)
Mar 07 Python
python应用文件读取与登录注册功能
Sep 23 Python
Python模块的制作方法实例分析
Dec 21 Python
使用Python将Exception异常错误堆栈信息写入日志文件
Apr 08 Python
python matlab库简单用法讲解
Dec 31 Python
python获取淘宝服务器时间的代码示例
Apr 22 Python
深入理解Pytorch微调torchvision模型
Nov 11 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计算几分钟前、几小时前、几天前的几个函数、类分享
2014/04/09 PHP
PHP结合JQueryJcrop实现图片裁切实例详解
2014/07/24 PHP
求帮忙修改个php curl模拟post请求内容后并下载文件的解决思路
2015/09/20 PHP
PHP 读取文本文件内容并分页显示
2016/01/02 PHP
PHP错误机制知识汇总
2016/03/24 PHP
PHP判断函数是否被定义的方法
2019/06/21 PHP
Javascript操纵Cookie实现购物车程序
2007/02/15 Javascript
div拖拽插件——JQ.MoveBox.js(自制JQ插件)
2013/05/17 Javascript
使用CSS+JavaScript或纯js实现半透明遮罩效果的实例分享
2016/05/09 Javascript
vue如何实现observer和watcher源码解析
2017/03/09 Javascript
详解JS获取HTML DOM元素的8种方法
2017/06/17 Javascript
js实现鼠标拖拽缩放div实例代码
2019/03/25 Javascript
webpack中如何加载静态文件的方法步骤
2019/05/18 Javascript
在Vue中使用icon 字体图标的方法
2019/06/14 Javascript
微信小程序自定义多列选择器使用详解
2019/06/21 Javascript
layerui代码控制tab选项卡,添加,关闭的实例
2019/09/04 Javascript
实例分析JS中的相等性判断===、 ==和Object.is()
2019/11/17 Javascript
Laravel 如何在blade文件中使用Vue组件的示例代码
2020/06/28 Javascript
node.js通过Sequelize 连接MySQL的方法
2020/12/28 Javascript
[46:53]Secret vs Liquid 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
简单解析Django框架中的表单验证
2015/07/17 Python
Python删除Java源文件中全部注释的实现方法
2017/08/30 Python
浅谈python迭代器
2017/11/08 Python
Python cookbook(数据结构与算法)找到最大或最小的N个元素实现方法示例
2018/02/13 Python
python人民币小写转大写辅助工具
2018/06/20 Python
python实现C4.5决策树算法
2018/08/29 Python
python 引用传递和值传递详解(实参,形参)
2020/06/05 Python
详解Flask前后端分离项目案例
2020/07/24 Python
HTML5实现锚点时请使用id取代name
2013/09/06 HTML / CSS
函授毕业自我鉴定
2014/02/04 职场文书
学生会竞选演讲稿
2014/04/24 职场文书
以幸福为主题的活动方案
2014/08/22 职场文书
刑事申诉状范文
2015/05/20 职场文书
素质拓展训练感想
2015/08/07 职场文书
你离财务总监还有多远?速览CFO的岗位职责
2019/11/18 职场文书
2021-4-3课程——SQL Server查询【2】
2021/04/05 SQL Server