開發每個Python項目時,都推薦創建對應的virtualenv來隔離開發。 這樣可以不受系統Python軟件包的影響,安裝任意包的任意版本,並且最終能通過pip freeze > requirements.txt
獲取依賴列表。當然,這個列表通常需要裁剪。
一、安裝virtualenv
使用apt、yum等包管理器安裝的版本老舊,推薦使用pip安裝。
python3.6 -m pip install virtualenv
二、準備virtualenv
每個項目,都需要獨立創建一個(或多個)虛擬環境,隔離開發。
virtualenv -p python3.6 venv
-p
是顯式指定Python版本,避免使用默認的python。- 虛擬環境的常用名,可選擇
env
、venv
、.env
、.venv
。
root@SS-DTA:/home/nbsprc# ls -alh
total 12K
drwxr-xr-x 3 root root 4.0K May 25 03:03 .
drwxr-xr-x 9 root root 4.0K May 25 02:52 ..
drwxr-xr-x 5 root root 4.0K May 25 03:03 venv
三、激活virtualenv
默認使用的是用戶+系統環境,激活後纔是虛擬環境。
source venv/bin/activate
激活虛擬環境後,可以看到只有三個Python包。 這個環境可以隨意使用,所有安裝都會在./venv/
下,不會影響系統環境。 乾淨的環境,也能幫助開發人員確認依賴。
(venv) root@SS-DTA:/home/nbsprc# pip list
Package Version
---------- -------
pip 19.1.1
setuptools 41.0.1
wheel 0.33.4
在這個虛擬環境中,python就是python3.6,而系統環境的python通常是python2。 在安裝軟件時,直接使用pip,即可安裝到虛擬環境中。 而不像一般狀態下,要麼加sudo提權([brew]或Windows環境下不用),要麼安裝時需要加–user,安裝到用戶目錄下。
四、退出virtualenv
deactivate
退出後,回到用戶+系統環境。
五、虛擬環境的原理
virtualenv是如何創建一個隔離的Python虛擬環境?這個環境有什麼特點?
這個環境的特點:
- Python版本固定。即使系統的Python升級了,虛擬環境中的仍然不受影響,保留開發狀態。
- 所有Python軟件包,都只在這個環境生效。一旦退出,則回到用戶+系統的默認環境中。
這兩個特點,由兩個小手段實現。
- 改變當前Shell的
PATH
。 - 改變Python運行時的
sys.path
。
改變PATH
root@SS-DTA:/home/nbsprc# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
(venv) root@SS-DTA:/home/nbsprc# echo $PATH
/home/nbsprc/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
顯然,這個activate,爲當前PATH增加了/home/nbsprc/venv/bin
這個位置在最前方,因此虛擬環境中的可執行文件擁有最高優先級。 而lib與include,僅僅是bin下面的可執行文件做相對路徑運算來尋找的位置。 所以,改變了PATH,就改變了很多事。
由於優先級最高,所以環境裏的python、pip等,包括後來用pip安裝的可執行文件,都使用的是venv下的。
改變sys.path
root@SS-DTA:/home/nbsprc# python3.6 -m site
sys.path = [
'/home/nbsprc',
'/usr/lib/python36.zip',
'/usr/lib/python3.6',
'/usr/lib/python3.6/lib-dynload',
'/usr/local/lib/python3.6/dist-packages',
'/usr/local/lib/python3.6/dist-packages/setuptools-41.0.1-py3.6.egg',
'/usr/lib/python3/dist-packages',
]
USER_BASE: '/root/.local' (exists)
USER_SITE: '/root/.local/lib/python3.6/site-packages' (doesn't exist)
ENABLE_USER_SITE: True
(venv) root@SS-DTA:/home/nbsprc# python -m site
sys.path = [
'/home/nbsprc',
'/home/nbsprc/venv/lib/python36.zip',
'/home/nbsprc/venv/lib/python3.6',
'/home/nbsprc/venv/lib/python3.6/lib-dynload',
'/usr/lib/python3.6',
'/home/nbsprc/venv/lib/python3.6/site-packages',
]
USER_BASE: '/root/.local' (exists)
USER_SITE: '/root/.local/lib/python3.6/site-packages' (doesn't exist)
ENABLE_USER_SITE: False
可見,sys.path
發生了翻天覆地的變化。 除了當前路徑/root
和標準庫/usr/local/lib/python3.6
被保留以外,其它位置都換成了venv下的。 這就是爲什麼pip list
看不見什麼軟件包的原因,也是環境隔離的最大祕密。