Python 自 3.3 版開始提供虛擬環境 (PEP405, virtual environments in core, Sept. 29, 2012).

個人以為主要是為了清理出一個乾淨開發環境, 以便將來布署時不會多出一些有的沒的 package:

  • 別的專案用的, 而且這個專案用不到的.
  • 正在測試學習的.
  • 或者猜想著這個 package 到底是有沒有用到 (不曾記得安裝過, 但實際上是因為和另一個 package 相依而自動安裝進來了).
  • 避免 package 和 python 本身不相容的問題. 同時也可以避免這些多出來 package 引發不相容的問題. (小弟不才只寫過二個 python 小專案, 引用的東西不多, 所以一直沒有遇到)

新版本的 python 可能或多或少會和一些 package 不相容, 尤其像是當年 python 3.0 那樣的大改版. 但是各個 package 之間的版本相依性也是經常會引發問題. 使用虛擬環境可以讓我們在構建專案時把環境先弄好, 並鎖定為專案的專用環境, 不必擔心因為別的專案的需求而弄壞了這個專案的環境.

比起另一個也是管理虛擬環境anaconda (since ver. 0.8.0, Jul. 13, 2012), python 自己所提供的虛擬環境管轄範圍小 (它只管 python 本身和 python packages), 所以使用上也相對的很簡便(註一):

  1. 先是針對專案進行開設虛擬環境.
  2. 設好之後, 所有和這個虛擬環境相關的工作 (安裝 packages, 測試/執行專案...等) 都要在虛擬環境啟動的狀態下進行. 所以, 新開啟的 bash terminal (或是 Windows Command Console) 使用前需要先啟動 (或者說是進入) 虛擬環境.
  3. 進入虛擬環境後, 所有的指令還是和沒有進入虛擬環境時完全一致, 不需要多加任何參數. 當然, 剛新開的虛擬環境裡面什麼 package 也沒有. 所以第一次啟動之後, 我們通常需要把要使用的 packages 遂一的安裝起來.
  4. 最後, 工作完成了, 就可以進行關閉 (或者說是離開) 虛擬環境.(註二)

註一: anaconda 管的多, 所以比較龐大 (anaconda 是動不動就幾個 GB 的怪獸, 真的很大), 所以只要是重覆的檔案都是使用連結 (link) 來建立複本. python 的虛擬環境也是盡可能的用 link, 但很可惜的是 windows 版是用 copy 的. 所以 windows 版中, 使用 python 的 venv 建立多少個虛擬環境, 就會有多少份 python.exe, pythonw.exe,pip.exe... 但因為 python 虛擬環境本身很小, 所以也算是可以接受.

註二: 其實是想關就關, 要用的時候再開即可.

所以總共三個新指令要認識一下:

  1. 開設
  2. 啟動
  3. 關閉

初始化: 開設虛擬環境


由於我們將會有各種不同的 虛擬環境, 為了方便區別, 我們需要為它命名. Python 會以此名稱建立一個目錄, 並將相關的資訊和檔案都放在該目錄中. 因此我們要先給虛擬環境取個簡單易懂的名字, 並決定它要放在哪裡. 然後執行下面的指令:

python -m venv /path/to/virtual_env_folder

Python 就會在你所指定的目錄中建立起虛擬環境 (目錄不存在 python 會自己幫你建立). 虛擬環境的管理 (命名及目錄位置) 可以依自己的需求, 我是直接在專案目錄裡, 進行開設虛擬環境. 例如:

# 直接開
$ python -m venv myProj\myEnv
# 或者分二段
$ cd myProj
$ python -m venv myEnv

這樣專案目錄 myProj 裡就有一個虛擬環境目錄 myEnv.

至於要不要把這個目錄放進 git 版本庫呢? 個人認為是不必, 因為有 pip freeze 指令可以產出需求的 packages 清單 (+版本需求), 只要使用
pip install -r 清單檔名
即可複製自己目前使用的 python 環境. 頂多是把 '清單檔名' 列入版本控制吧. 這樣子, 我們可以不必強制要求開發者用什麼名字作為虛擬環境的名字.

(myEnv) $ pip freeze > dependency.txt
(yourEnv) $ pip install -r dependency.txt

如果 python 或者 package 需要進行升版, 也可以利用這個方法, 暫時另開一個虛擬環境, 進行升版及測試, 而不必動到原本的虛擬環境(註三, 註四).

另外, 我發現一些初學者對於專案目錄和虛擬環境的界定不清楚, 常常會把自己的程式 (.py 檔或者 .ipynb 檔) 放進虛擬環境的目錄裡. 請千萬不要這麼做. 請你務必記得不要把自己的程式放進虛擬環境的目錄裡.

註三: 注意: 虛擬環境開設後, 不要對虛擬環境目錄進行任何更名/搬動/複製 (任何影響到虛擬環境絕對路徑的活動都不行). 搬動它會使你的虛擬環境錯亂; 複製它, 複製出來的虛擬環境還是和原來的相關, 而不是獨立的一份. 這是因為, 目前 venv 在產生 activate 批次檔時是將虛擬環境的路徑 myEnv 直接寫死在檔案裡. activate 執行時就將該目錄下的Scripts 子目錄 (myEnv/Scripts, 而不是執行時自行判定目前所在位置) 附加在環境變數 PATH的最前面. 不過如果你自己有把握, 可以修正這些問題, 那就不在此限 (後果自負, 不要說我沒有提醒你; 另一個原因是還有許多 package 的 .pyc 檔都有記錄其全路徑.)

註四: 測完沒用的虛擬環境, 直接刪除即可. 萬一測試失敗, 可能會有 process 卡住而使得虛擬環境刪不乾淨, 則 window 關掉重開, 再刪一次就可以了. (Win7 有遇到過, Win10 用到現在還沒有發生過)

虛擬環境目錄結構


Windows 環境下所開出來的虛擬環境目錄結構如下圖:

python venv.png

Windows 環境的虛擬環境目錄結構

其中比較重要的是檔案 pyvenv.cfg 以及 LibScripts 這二個目錄.

  • pyvenv.cfg 是這個虛擬環境的設定檔.
  • Scripts 裡放的是相關的執行檔dll, 如: python.exe, activate.bat.
  • 而我們之後使用 pip install 安裝的 packages 都會進到 Lib/site-packages 這個目錄.
  • 另外, packages 若含有相關的 執行檔dll 則也會加到 Scripts 目錄中.

OSX 與 Linux 環境二者和 Windows 環境主要的差異是 Scripts 目錄改為 bin, 還有 activate.bat 變成了沒有附檔名的 bash script activate.

啟動虛擬環境


OSX 和 Linux 環境下, 請使用以下指令:

source myEnv/bin/activate

或者 Windows 指令

myEnv\Scripts\activate.bat

請把其中的 myEnv 要換成你自己設定的虛擬環境目錄名稱. 啟動虛擬環境之後, 系統提示符號之前會多一個 (myEnv), 用以提醒我們是在虛擬環境中.

OSX 和 Linux 環境的提示如下:

(myEnv) $

或者 Windows 系統提示:

(myEnv) D:\>

其實說穿了, 啟動虛擬環境並沒有幹什麼大事, 只是

  • 虛擬環境下的 Scripts 路徑加到環境變數 PATH 的最前面, 讓系統優先找到放在它底下的 python 執行檔.
  • 改一下系統提示, 把虛擬環境的目錄名加在原本的系統提示前面.

如此而已. 這也是為什麼虛擬環境可以想關就關, 要用再開. 還有新開啟的 bash terminal (或是 Windows Command Console) 使用前需要先啟動 (或者說是進入) 虛擬環境.

關閉虛擬環境


OSX, Linux 和 Windows 環境都是使用以下指令:

deactivate

下達指令之後, 環境變數 PATH 和系統提示會回復到原本的樣子.

因為並沒有什麼程式在背後執行, 所以如果把啟動虛擬環境的 bash 終端機 (或 Windows command console) 直接關掉並不會引發任何問題.

其他相關指令


升級虛擬環境內的 python


虛擬環境的 python 升級了 (或者重新安裝, 換路徑了也行), 如果也想要將虛擬環境的 python 也升級上來, 怎麼辦呢?

python -m venv --upgrade myEnv

另外, 由於啟動虛擬環境後, 虛擬環境的 Scripts (或者 bin) 路徑會自動附加在環境變數 PATH 的最前面, 所以 Python 安裝時並不需要修改環境變數 PATH. (我們只有在新設定虛擬環境時需要它, 平時的工作完全不需要, 更何況 Windows 平台還有一個 Python Launcher: py.exe 可以用來啟動不同版本的 python.)

查看 python 系統環境


我們可以查看一下 python 系統環境在沒有啟動虛擬環境, 和啟動了之後 有何不同. 下面列的是啟動虛擬環境後的:

(vLAB2) D:\Works\jupyter> python -m site
sys.path = [
    'D:\\Works\\jupyter',
    'D:\\Python38\\python38.zip',
    'D:\\Python38\\DLLs',
    'D:\\Python38\\lib',
    'D:\\Python38',
    'D:\\Works\\jupyter\\vLAB2',
    'D:\\Works\\jupyter\\vLAB2\\lib\\site-packages',
    'D:\\Works\\jupyter\\vLAB2\\lib\\site-packages\\win32',
    'D:\\Works\\jupyter\\vLAB2\\lib\\site-packages\\win32\\lib',
    'D:\\Works\\jupyter\\vLAB2\\lib\\site-packages\\Pythonwin',
]
USER_BASE: 'C:\\Users\\User001\\AppData\\Roaming\\Python' (exists)
USER_SITE: 'C:\\Users\\User001\\AppData\\Roaming\\Python\\Python38\\site-packages' (exists)
ENABLE_USER_SITE: False

應該至少會有 4 組不同. 最重要的, 使用 python 執行檔的來源不同, 還有 ENABLE_USER_SITE 變成 False 了.

VS code 與 虛擬環境


MS VS Code 認得 Python 的虛擬環境: MS VS Code 可以和anaconda的虛擬環境配合, 也可以和 Python 自己的虛擬環境配合.

請注意: VS Code 只認得專案目錄以下的 venv 虛擬環境, 所以務必設定並開啟一個專案目錄並將 venv 虛擬環境開設在專案目錄下 (在專案目錄以下即可, 不限定一定要開在第一層子目錄).

如果虛擬環境還沒有開設, 建議你直接在 VS Code 的終端機環境中直接開設. VS Code 會問你是不是要直接將 python interpreter 設定成使用這個新開的虛擬環境, 可以省去自己設定的麻煩. 如果虛擬環境已經開設了, 則請使用下述的方法.

例如我已經開設好一個虛擬環境 vLAB2, 在 windows command console 中, 啟動虛擬環境 vLAB2 之後, 輸入:

(vLAB2) D:\Works\jupyter\> code .

進入 VS Code 之後, 按 Ctrl+Shift+P (或者 F1), 輸入 python: select interpreter, 然後選擇位於 vLAB2/Scripts 子目錄中的 python.exe.

設好之後, 你應該可以看到左下方的 python 指示器應該改為有帶虛擬環境名字的指示 (vLAB2). 這時在 VS Code 執行 (或者除錯) python 程式時, 都會在虛擬環境中進行.

/tmp/php4MRfsj

VS Code 中使用 python venv. 虛擬環境名稱為 vLAB2

如果想在虛擬環境中安裝工作 python package, 我們不必一定要另外開啟一個 Windows command console 來工作. 直接在 VS Code 裡開一個新的 terminal 視窗就可以看到進入虛擬環境的系統提示符號 (或者由原本的 terminal 輸入啟動虛擬環境的指令也可以).

其他


其他的指令和沒在進入虛擬環境之前的都一樣.

相關文章連結


更新 2020/11/11


才剛說嘴就打嘴, 昨天安裝 python 3.9 + jupyterlab + jupyterlab-git + matplotlib 失敗了. 好在原本的環境完好如初. 同時幾經奮鬥也終於完成新環境的設定, 改天再把解法整理出來. (請參考這一篇貼文)

    MagicJackTing 發表在 痞客邦 留言(0) 人氣()