python多環境管理一(venv與virtualenv)

doublexi發表於2022-01-10

一、背景

我們經常會遇見這樣的場景:

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

如下圖:

clipboard[63]_thumb[1]

bin下面是pip、python等一些可執行環境,

pyvenv.cfg 是我們的配置檔案,為什麼叫 pyvenv,因為這個庫的前身就叫 pyvenv。

而我們的 site-packages 就在 lib 目錄下。

clipboard[64]_thumb[1]

啟用虛擬環境:

cd /data/myproj source ./bin/activate

如下圖,命令列最前面會顯示環境名。

clipboard[65]_thumb[1]

啟用後,你使用的python,指向的就是虛擬環境裡的python了,如下:

clipboard[66]_thumb[1]

在虛擬環境下安裝包,啟動專案

(myproj) [root@ops-130 myproj]# pip install sqlalchemy

發現安裝的包會放在當前環境目錄下的lib裡面。

clipboard[67]_thumb[1]

這樣,我們只要啟用虛擬環境後,在虛擬環境下啟動專案,即可實現跟其他專案環境隔離了。

注意:專案程式碼不需要放在虛擬環境目錄下,任意位置即可,只需要啟用對應虛擬環境。

退出虛擬環境:

(myproj) [root@ops-130 myproj]# deactivate 

如下,啟用前後對比:

clipboard[68]_thumb[1]

當前預設python為2.7,預設python3為python3.6.15,另外還裝有python3.9.9

如果需要指定python版本為3.9.9,可以這樣使用:

python3.9 -m venv myproj2

如下圖:這樣就能夠達到使用不同版本的python了。

clipboard[69]_thumb[1]

注意: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

如下圖:

clipboard[70]_thumb[1]

它會在當前路徑下,建立myenv5的目錄,虛擬環境的所有命令和包都在這個目錄下。

clipboard[71]_thumb[1]

bin:存放一些python、pip命令的目錄

virtualenv的軟體包管理目錄site-package在lib/python3.6/site-packages/下。

如下圖:

clipboard[72]_thumb[1]

啟用虛擬環境

source  /data/myenv5/bin/activate

如下圖:

clipboard[73]_thumb[1]

退出虛擬環境:

deactivate

如下圖:

clipboard[74]_thumb[1]

刪除虛擬環境,只需要將這個虛擬環境目錄刪除即可。

rm -rf myenv5

指定python直譯器:

建立的虛擬環境的python直譯器,預設使用virtualenv裡的版本。

如果你是把virtualenv安裝在python2裡,那預設的就是python2,安裝在python3裡,預設的就是python3。當然,你也可以自己指定使用哪個直譯器版本,比如:

virtualenv myvenv6 -p python3.9

建立的虛擬環境如下圖:

clipboard[75]_thumb[1]

繼承基礎環境的包

virtualenv從版本20開始,預設就是’--no-site-packages‘了,預設就是不繼承父環境的包。建立的虛擬環境是一個不帶任何第三方包的“乾淨”的Python執行環境。

如果有教程告訴你,“--no-site-packages選擇不繼承父環境的包”,這個命令已經廢棄了。

那麼,如果你現在想要繼承父環境的包,怎麼辦?使用--system-site-packages

先在父環境,pip安裝一個包jieba

pip3 install jieba

建立一個可以訪問基礎環境包的虛擬環境:

virtualenv --system-site-packages myvenv7

如下圖:

clipboard[76]_thumb[1]

進入虛擬目錄,檢視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/

如下圖:它並沒有將包拷貝過來。

clipboard[77]_thumb[1]

我們使用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生效了。

clipboard[78]_thumb[1]

其他詳細介紹,請參考 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

如下圖:

clipboard[79]_thumb[1]

啟用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

如下圖:

clipboard[80]_thumb[1]

注意:如果你安裝的virtualenv不在系統預設的python直譯器上,就需要單獨指定virtualenvwrapper使用的python路徑:VIRTUALENVWRAPPER_PYTHON,否則啟用的時候,會報錯,如下:

No module named virtualenvwrapper

如下報錯,因為它預設使用系統的python路徑了。

clipboard[81]_thumb[1]

新增VIRTUALENVWRAPPER_PYTHON變數即可。

export VIRTUALENVWRAPPER_PYTHON=/usr/local/python3.6/bin/python3

2、virtualenvwrapper使用

建立虛擬環境 mkvirtualenv

mkvirtualenv venv8

如下圖:建立的同時,還預設啟用了虛擬環境

clipboard[82]_thumb[1]

虛擬環境目錄不會放到當前目錄下了,它預設裝在了/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

如下圖:

clipboard[83]_thumb[1]

檢視當前的虛擬環境目錄

(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

https://virtualenv.pypa.io/en/latest/reference/

https://virtualenvwrapper.readthedocs.io/

相關文章