一、背景
我们经常会遇见这样的场景:
1、各个项目使用的python版本不相同
由于Python的解释器版本众多,各版本之间差异非常大。特别是python2和python3,互不兼容。
有些项目可能用的python2.7,有些项目可能用的是python3.6,有些则使用的3.8等,但是它们却需要运行在同一个服务器环境中。(docker除外,docker容器可以隔离不同的项目环境。)
2、系统依赖自带的解释器
系统的一些服务组件一般也会依赖Python环境。不同的Linux发行版自带的Python也不同。如ubuntu16自带2.7和3.5版本, Centos7依赖python2.7。而系统很多组件都依赖自带的解释器,比如yum等,你不能轻易删除这个版本,一旦删除或者更改都可能造成系统出问题。
3、依赖默认的解释器路径冲突
比如Centos7系统自带的python是2.7,系统很多组件比如yum依赖的都是2.7这个版本。但是我们发现这些工具开头使用的都是:#!/usr/bin/python。
而一些新的使用python开发的服务组件,它们依赖的确实python3.6以上的版本,但是它们一些代码开头用的也是这个引用:#!/usr/bin/python。
它们都是用python这一个引用,却没有使用python2、python3这样分开,这就很容易导致它们的一些python引用冲突。
4、依赖冲突。(最常见)
我们都知道python的软件包依赖经常是个很头疼的问题,经常因为这个问题导致到家在安装一些python环境或者服务组件时失败。
而不同的python解释器版本,对软件包依赖库的管理也是个问题。
比如sqlalchemy这个包,有些项目使用的python2.7版本,它需要依赖这个库,有些项目使用的python3.6版本,它也需要依赖这个库,有些项目使用的python3.8版本,它同样也需要依赖这个库,
但是头疼的是,这三者它们依赖的这个包版本还不一致。sqlalchemy从0.1-2.0有众多版本。
这时候如果你在系统上直接使用pip install sqlalchemy的话,它只能选择安装一个版本,但是这样其他两个项目是无法使用这个版本,就会出现依赖冲突的问题。
由于 Python 的依赖库管理是中心化的,而且大版本上的不兼容且长期并行,就出现了这么一个独特的话题。
你的环境隔离了吗?
二、多环境隔离解决方案
那么有没有一个终极的解决办法能在管理不同解释器版本的同时控制不同的包环境呢?
有的,Python 社区已经涌现了众多这种工具。
Python 多环境隔离,可以让你的每个项目拥有独立的依赖库,即 site-packages。
三、venv
为什么把 venv 放在第一个,因为它是自 3.3 版本之后添加的官方库,自 3.6 版本之后,成为官方推荐的多环境管理工具。也就是说,你不需要安装任何第三方库就可以实现多环境管理了。
注意:python3.3版本之后自带的模块,只支持3.3版本之后的,不支持2.x
1、虚拟环境管理
使用venv创建虚拟隔离环境:
python3 -m venv /data/myproj
它会创建/data/myproj目录,下面如下:
ll /data/myproj
如下图:
bin下面是pip、python等一些可执行环境,
pyvenv.cfg 是我们的配置文件,为什么叫 pyvenv,因为这个库的前身就叫 pyvenv。
而我们的 site-packages 就在 lib 目录下。
激活虚拟环境:
cd /data/myproj source ./bin/activate
如下图,命令行最前面会显示环境名。
激活后,你使用的python,指向的就是虚拟环境里的python了,如下:
在虚拟环境下安装包,启动项目
(myproj) [root@ops-130 myproj]# pip install sqlalchemy
发现安装的包会放在当前环境目录下的lib里面。
这样,我们只要激活虚拟环境后,在虚拟环境下启动项目,即可实现跟其他项目环境隔离了。
注意:项目代码不需要放在虚拟环境目录下,任意位置即可,只需要激活对应虚拟环境。
退出虚拟环境:
(myproj) [root@ops-130 myproj]# deactivate
如下,激活前后对比:
当前默认python为2.7,默认python3为python3.6.15,另外还装有python3.9.9
如果需要指定python版本为3.9.9,可以这样使用:
python3.9 -m venv myproj2
如下图:这样就能够达到使用不同版本的python了。
注意:venv只能使用当前系统已经安装好的python,无法使用其他版本的python环境。
2、优缺点分析:
1、venv是python3自带的,不需要额外安装库就能运行。
2、只能在3.3版本以后,2.x用不了
3、venv过于简单,没有额外的api。只能创建个虚拟环境,不能指定系统不存在的python环境版本,不能查看环境列表。
四、virtualenv
virtualenv 是目前最流行的 python 虚拟环境配置工具。它不仅同时支持 python2 和 python3,而且可以为每个虚拟环境指定 python 解释器,并可以选择继承基础版本的包。
virtualenv 可以说是 venv 的增强版本,不过早在 venv 出现之前,virtualenv 就算是最受欢迎的命令行环境管理工具了。venv 的许多特性也是借鉴的 virtualenv,相比于 venv,其强大之处主要在:
更快
扩展性更强
自动发现并可创建多版本的 Python 环境
可通过 pip 更新
丰富的编程接口
1、安装virtualenv
使用自己对应安装的pip版本
pip3 install virtualenv
2、常见虚拟环境管理操作
创建虚拟环境目录
cd /data virtualenv myenv5
如下图:
它会在当前路径下,创建myenv5的目录,虚拟环境的所有命令和包都在这个目录下。
bin:存放一些python、pip命令的目录
virtualenv的软件包管理目录site-package在lib/python3.6/site-packages/下。
如下图:
激活虚拟环境
source /data/myenv5/bin/activate
如下图:
退出虚拟环境:
deactivate
如下图:
删除虚拟环境,只需要将这个虚拟环境目录删除即可。
rm -rf myenv5
指定python解释器:
创建的虚拟环境的python解释器,默认使用virtualenv里的版本。
如果你是把virtualenv安装在python2里,那默认的就是python2,安装在python3里,默认的就是python3。当然,你也可以自己指定使用哪个解释器版本,比如:
virtualenv myvenv6 -p python3.9
创建的虚拟环境如下图:
继承基础环境的包
virtualenv从版本20开始,默认就是’--no-site-packages‘了,默认就是不继承父环境的包。创建的虚拟环境是一个不带任何第三方包的“干净”的Python运行环境。
如果有教程告诉你,“--no-site-packages选择不继承父环境的包”,这个命令已经废弃了。
那么,如果你现在想要继承父环境的包,怎么办?使用--system-site-packages
先在父环境,pip安装一个包jieba
pip3 install jieba
创建一个可以访问基础环境包的虚拟环境:
virtualenv --system-site-packages myvenv7
如下图:
进入虚拟目录,查看python版本:
[root@ops-130 data]# cd myvenv7/ [root@ops-130 myvenv7]# source ./bin/activate (myvenv7) [root@ops-130 myvenv7]# python -V Python 3.6.15 (myvenv7) [root@ops-130 myvenv7]# pip -V pip 21.3.1 from /data/myvenv7/lib/python3.6/site-packages/pip (python 3.6) (myvenv7) [root@ops-130 myvenv7]# ls /data/myvenv7/lib/python3.6/site-packages/
如下图:它并没有将包拷贝过来。
我们使用python看能否导入父环境的包:
(myvenv7) [root@ops-130 myvenv7]# python Python 3.6.15 (default, Dec 31 2021, 15:08:17) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import jieba >>>
没有问题,说明可以访问父环境的包。--system-site-packages生效了。
其他详细介绍,请参考 virtutalenv 官网:https://virtualenv.pypa.io/en/latest/reference/
3、优缺点:
1、跟venv基本一致,功能过于简单,就只是创建个虚拟隔离环境,没有多余功能。
2、相比venv,它支持在2.x、3.x以及windows,
3、相比venv,可以指定python版本与选择是否继承父环境的包。(venv也可以指定版本)
4、这里virtualenv 有些不便,因为virtual的启动、停止脚本都在特定文件夹,可能一段时间后,你可能会有很多个虚拟环境散落在系统各处,你可能忘记它们的名字或者位置。
这一点远没有pyenv好。
五、virtualenvwrapper
鉴于virtualenv不便于对虚拟环境集中管理,所以推荐直接使用virtualenvwrapper。 virtualenvwrapper提供了一系列命令使得和虚拟环境工作变得便利。它把你所有的虚拟环境都放在一个地方。
官网参考:https://virtualenvwrapper.readthedocs.io/
1、安装virtualenvwrapper(确保virtualenv已安装)
pip3 install virtualenv pip3 install virtualenvwrapper pip3 install virtualenvwrapper-win #Windows使用该命令
virtualenvwrapper默认将所有的虚拟环境放在~/.virtualenvs目录下管理,可以修改环境变量WORKON_HOME来指定虚拟环境 的保存目录。
# 可选 # 修改virtualenvwrapper的虚拟环境存放目录 mkdir -p /data/virtualenvs/ # 可选,我们这里安装在默认的 vim /etc/profile # virtualenvwrapper export WORKON_HOME=$HOME/.virtualenvs export PROJECT_HOME=$HOME/Devel
source加载使生效
source /etc/profile
虽然已经pip安装了,但是此时,你依然无法使用virtualenvwrapper
上面的virtualenvwrapper被安装到了你使用pip3的python环境下,如下:
[root@ops-130 test]# ls /usr/local/python3.6/bin/virtualenvwrapper.sh /usr/local/python3.6/bin/virtualenvwrapper.sh
如下图:
激活virtualenvwrapper
source /usr/local/python3.6/bin/virtualenvwrapper.sh
可以将这个命令也一起放到环境变量中,.bashrc
vim /root/.bashrc # virtualenvwrapper export WORKON_HOME=$HOME/.virtualenvs export PROJECT_HOME=$HOME/Devel VIRTUALENVWRAPPER_PYTHON=/usr/local/python3.6/bin/python3 source /usr/local/python3.6/bin/virtualenvwrapper.sh
如下图:
注意:如果你安装的virtualenv不在系统默认的python解释器上,就需要单独指定virtualenvwrapper使用的python路径:VIRTUALENVWRAPPER_PYTHON,否则激活的时候,会报错,如下:
No module named virtualenvwrapper
如下报错,因为它默认使用系统的python路径了。
添加VIRTUALENVWRAPPER_PYTHON变量即可。
export VIRTUALENVWRAPPER_PYTHON=/usr/local/python3.6/bin/python3
2、virtualenvwrapper使用
创建虚拟环境 mkvirtualenv
mkvirtualenv venv8
如下图:创建的同时,还默认激活了虚拟环境
虚拟环境目录不会放到当前目录下了,它默认装在了/root/.virtualenvs,所有的虚拟环境都会放到这个目录下
(venv8) [root@ops-130 data]# ls /root/.virtualenvs/venv8/ bin lib pyvenv.cfg
如果想要指定python版本,可以使用--python命令
mkvirtualenv --python=/usr/local/python3.9/bin/python3 venv9 # 有环境变量可以简化 mkvirtualenv --python=python3.9 venv9
如下图:
查看当前的虚拟环境目录
(venv9) [root@ops-130 data]# workon venv8 venv9
切换虚拟环境
(venv9) [root@ops-130 data]# workon venv8 (venv8) [root@ops-130 data]# python -V Python 3.6.15
退出虚拟环境
(venv8) [root@ops-130 data]# deactivate [root@ops-130 data]#
删除虚拟环境
rmvirtualenv venv8
virtualenvwrapper 提供环境名字的tab补全功能。当您有很多环境, 并且很难记住它们的名字时,这就显得很有用。
workon 也能停止您当前所在的环境,所以您可以在环境之间快速的切换。
其它命令参考:https://virtualenvwrapper.readthedocs.io/en/latest/
3、优缺点分析:
1、它就是基于virtualenv的封装,将所有虚拟环境整合在一个目录下,默认(~/.virtualenvs)
2、提供了很多api,可以管理(新增,删除,复制,切换)虚拟环境
3、支持tab补全,切换环境很方便。
参考:
https://zhuanlan.zhihu.com/p/106588887