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框架中select_related和prefetch_related函数对数据库查询优化
Apr 01 Python
Python中的匿名函数使用简介
Apr 27 Python
Python中if __name__ == '__main__'作用解析
Jun 29 Python
python selenium 获取标签的属性值、内容、状态方法
Jun 22 Python
详解分布式任务队列Celery使用说明
Nov 29 Python
Python+PyQt5实现美剧爬虫可视工具的方法
Apr 25 Python
Python中的引用知识点总结
May 20 Python
python3 实现调用串口功能
Dec 26 Python
python程序文件扩展名知识点详解
Feb 27 Python
python实现交并比IOU教程
Apr 16 Python
Django Channel实时推送与聊天的示例代码
Apr 30 Python
python爬虫请求库httpx和parsel解析库的使用测评
May 10 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之短标签开启设置
2013/06/17 PHP
浅析ThinkPHP的模板输出功能
2014/07/01 PHP
JavaScript实现动态删除列表框值的方法
2015/08/12 Javascript
详解javascript数组去重问题
2015/11/06 Javascript
javascript实现标签切换代码示例
2016/05/22 Javascript
jquery.tableSort.js表格排序插件使用方法详解
2020/08/12 Javascript
CodeMirror js代码加亮使用总结
2017/03/25 Javascript
浅谈对Angular中的生命周期钩子的理解
2017/07/31 Javascript
vue中进入详情页记住滚动位置的方法(keep-alive)
2018/09/21 Javascript
详解nodejs 配置文件处理方案
2019/01/02 NodeJs
重学JS 系列:聊聊继承(推荐)
2019/04/11 Javascript
JavaScript使用面向对象实现的拖拽功能详解
2019/06/12 Javascript
javascript实现留言板功能
2020/02/08 Javascript
JavaScript监听键盘事件代码实现
2020/06/03 Javascript
js实现头像上传并且可预览提交
2020/12/25 Javascript
Python实现提取文章摘要的方法
2015/04/21 Python
django允许外部访问的实例讲解
2018/05/14 Python
pyqt5 使用label控件实时显示时间的实例
2019/06/14 Python
python接口自动化如何封装获取常量的类
2019/12/24 Python
python使用pandas抽样训练数据中某个类别实例
2020/02/28 Python
python中实现栈的三种方法
2020/12/19 Python
极简的HTML5模版
2015/07/09 HTML / CSS
canvas实现滑动验证的实现示例
2020/08/11 HTML / CSS
西班牙宠物用品和食品网上商店:Tiendanimal
2019/06/06 全球购物
Onzie官网:美国时尚瑜伽品牌
2019/08/21 全球购物
GOLFINO英国官网:高尔夫服装
2020/04/11 全球购物
办公室文书岗位职责
2013/12/16 职场文书
查环查孕证明
2014/01/10 职场文书
回门宴父母答谢词
2014/01/26 职场文书
学历公证书范本
2014/04/09 职场文书
事业单位人员的自我评价范文
2014/09/21 职场文书
单方离婚协议书范本(2014版)
2014/09/30 职场文书
2015清明节祭奠英烈寄语大全
2015/03/04 职场文书
课改心得体会范文
2016/01/25 职场文书
JavaWeb 入门:Hello Servlet
2021/07/16 Java/Android
深入讲解数据库中Decimal类型的使用以及实现方法
2022/02/15 MySQL