1. 程式人生 > 程式設計 >Python 虛擬環境工作原理解析

Python 虛擬環境工作原理解析

Python 的虛擬環境用來建立一個相對獨立的執行環境,尤其是一些依賴的三方包,最常見的如不同專案依賴同一個但是不同版本的三方包,而且,在虛擬環境中的安裝包不會影響到系統的安裝包。

不過,其具體的工作原理是怎樣的,這裡詳細介紹。

簡介

幾乎每個語言都包含自己的包管理工具,這是一個非常複雜的話題,而不同語言選擇的實現又略有區別,都會做一些選擇和取捨。而 Python 的包管理解決方案很多,例如 pip、virtualenv、pyenv 等等。

不過 Python 語言本身的機制決定了其原理一樣。

使用

比較常用的是 virtualenv 工具,可以參考 Guide to Python 中的詳細介紹,另外,Python3 也提供了自己的虛擬環境建立模組,在建立完成後基本都是通過一個指令碼啟用獨立環境。

例如,如下是使用 virtualenv 以及 venv 的虛擬環境建立過程。

$ mkdir /tmp/project && cd /tmp/project

$ virtualenv --no-site-packages foobar
$ python3 -m venv foobar

然後,就可以通過 source foobar/bin/activate 命令啟用新環境。

啟用指令碼

所謂的獨立環境,無非就是解決兩個問題:A) 執行 Python 解析器所使用的版本;B) 使用獨立的包。其中前者,在 Linux 主要是通過 PATH 環境變數設定,在 activate 指令碼中有如下的內容。

VIRTUAL_ENV="/tmp/project/foobar"
export VIRTUAL_ENV

_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH

也就是將建立的目錄新增到 PATH 環境變數最開始,那麼就會優先查詢該路徑,這樣就解決了 python 解析器獨立的問題。

工作原理

如果要使用獨立的包,那麼關鍵就是如何在通過 import 匯入時查詢到所需的包。

包的查詢順序可以檢視Python 模組簡介 中的介紹,簡單來說,就是先檢視是否是內建模組,然後再從 sys.path 列表指定的地址中搜索。所以,這裡的關鍵就是 sys.path

列表的生成。

關於 sys.prefix

在 Python 啟動的時候,會先載入一個強依賴的 os.py 包,而查詢這個包是根據解析器的當前路徑,以及固定的查詢規則來實現的。

簡單來說,就是在當前路徑加上 lib/python${VERSION}/os.py 逐層向上查詢,注意,如果是 64 位的作業系統,那麼會使用 lib64 替換掉之前的 lib 路徑。

例如,預設的 Python3 的解析器路徑為 /usr/bin/python3.6 ,那麼基礎路徑是 /usr/bin/ ,所以,其查詢順序為。

/usr/bin/lib64/python3.6/os.py
/usr/lib64/python3.6/os.py
/lib64/python3.6/os.py

只要在任意路徑上找到 os.py 包,那麼就會退出查詢,並設定好 sys.prefix 變數,詳細可以通過 strace python 檢視,會有如下的搜尋路徑。

stat("/usr/bin/Modules/Setup",0x7fffb7146300) = -1 ENOENT (No such file or directory)
stat("/usr/bin/lib64/python2.7/os.py",0x7fffb71462f0) = -1 ENOENT (No such file or directory)
stat("/usr/bin/lib64/python2.7/os.pyc",0x7fffb71462f0) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/python2.7/os.py",{st_mode=S_IFREG|0644,st_size=25910,...}) = 0

在查詢到 os.py 之後,會將該路徑設定為 sys.prefix 變數,然後解析器就會到 ${sys.prefix}/lib/python${VERSION} 目錄下查詢包。

總結

那麼其工作原理就是,將 python 解析器儲存在 ${VENV_PATH}/bin/python ,然後建立 ${VENV_PATH}/lib/python${VERSION} 目錄,並將相關的檔案複製到該目錄下,可以複製檔案,也可以使用軟連線。

其它

如上,如果是 Python3 就可以直接使用內建的 venv 模組,其原理與上述的相同,同時通過 pyvenv.cfg 配置檔案來標識原始的 home 位置,該檔案的內容如下。

home = /usr/bin
include-system-site-packages = false
version = 3.6.8

如果 include-system-site-packagestrue ,直譯器啟動時就會將系統的庫新增到 sys.path 裡面,這樣在虛擬環境就可以 import 系統中安裝的包了。

注意,Python3 提供的 venv 模組只能根據當前版本建立,不能支援 Python2 。

參考 Virtualenv 官方文件,細節可以參考該文件。

Creation of virtual environments Python3 提供的 venv 介紹,包括常見引數以及配置檔案。

← Older

到此這篇關於Python 虛擬環境工作原理解析的文章就介紹到這了,更多相關Python 虛擬環境原理內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!