表的內容

  • 為什麼需要虛擬環境?
  • 什麼是虛擬環境?
  • 使用虛擬環境
  • 虛擬環境如何工作?
  • 使用virtualenvwrapper管理虛擬環境
  • 使用不同版本的Python

結論

在本文中,我們將向您展示如何使用虛擬環境為Python項目創建和管理單獨的環境,每個項目使用不同版本的Python執行。我們還將研究如何存儲和解析Python依賴項。

  • 更新的2018-01-12:明確pyenv vs. venv在Python 3.6+上的使用
  • 更新的2016-06-11:增加了關於使用virtualenv修改Python版本的部分

為什麼需要虛擬環境?

與大多數其他現代編程語言一樣,Python有自己獨特的下載、存儲和解析包(或模塊)的方式。雖然這有它的優點,但是在包存儲和解析方面做出了一些有趣的決定,這導致了一些問題——特別是關於如何存儲包以及在哪裡存儲包。

有幾個不同的位置可以在系統上安裝這些包。例如,大多數系統包存儲在sys.prefix中存儲的路徑的子目錄中。

在Mac OS X上,你可以很容易地找到sys的位置。前綴指向使用Python shell

import sys
sys.prefix
/System/Library/Frameworks/Python.framework/Versions/3.5

與本文主題更相關的是,使用easy_install或pip安裝的第三方包通常放site.getsitepackages所指向的目錄之一中:

import site
site.getsitepackages()
[
/System/Library/Frameworks/Python.framework/Versions/3.5/Extras/lib/python,
/Library/Python/3.5/site-packages
]

那麼,為什麼所有這些小細節都很重要呢?

瞭解這一點很重要,因為在默認情況下,系統上的每個項目都將使用這些相同的目錄來存儲和檢索站點包(第三方庫)。乍一看,這似乎不是什麼大問題,對於系統包(作為標準Python庫的一部分的包)來說也不是,但是對於站點包來說確實很重要。

考慮以下場景,其中您有兩個項目:ProjectA和ProjectB,它們都依賴於相同的庫ProjectC。當我們開始需要不同版本的ProjectC時,問題就變得很明顯了。例如,也許ProjectA需要v1.0.0,而ProjectB需要更新的v2.0.0。

這對於Python來說是一個真正的問題,因為它不能區分站點包目錄中的版本。所以v1.0.0和v2.0.0都位於相同的目錄中,名稱相同:

/System/Library/Frameworks/Python.framework/Versions/3.5/Extras/lib/python/ProjectC

因為項目是根據它們的名稱存儲的,所以版本之間沒有區別。因此,項目ProjectA和ProjectB都需要使用相同的版本,這在許多情況下是不可接受的。

這就是虛擬環境和virtualenv/venv工具發揮作用的地方。

我整理了Python的相關學習視頻及學習路線圖。

需要資料的,私信【學習】獲取更多資料 或者加我聯繫方式: 925916955

什麼是虛擬環境?

在其核心部分,Python虛擬環境的主要目的是為Python項目創建一個隔離的環境。這意味著每個項目都可以有自己的依賴項,而不管其他項目有什麼依賴項。

在上面的小示例中,我們只需要為ProjectA和ProjectB創建一個單獨的虛擬環境,就可以了。反過來,每個環境都能夠獨立於其他環境,依賴於它們選擇的ProjectC的任何版本。

這樣做的好處是,您可以擁有的環境數量沒有限制,因為它們只是包含一些腳本的目錄。另外,使用virtualenv或pyenv命令行工具很容易創建它們。

使用虛擬環境

首先,如果您不使用Python 3,那麼您將希望使用pip安裝virtualenv工具:

$ pip install virtualenv

如果使用Python 3,那麼應該已經安裝了標準庫中的venv模塊。

注意:從這裡開始,我們假設您使用的是更新的venv工具,因為它與virtualenv在實際命令方面沒有什麼區別。但實際上,它們是非常不同的工具。

從創建一個新的目錄開始:

$ mkdir python-virtual-environments && cd python-virtual-environments

在目錄中創建一個新的虛擬環境:

# Python 2:

$ virtualenv env

# Python 3$ python3 -m venv env

注意:默認情況下,這將不包括任何現有的站點包。

Python 3 venv方法的優點是迫使您選擇Python 3解釋器的特定版本,該版本應該用於創建虛擬環境。這就避免了

Python 3 venv方法的優點是迫使您選擇Python 3解釋器的特定版本,該版本應該用於創建虛擬環境。這避免了關於新環境所基於的Python安裝的任何混淆。

從Python 3.3到3.4,建議的創建虛擬環境的方法是使用pyvenv命令行工具,默認情況下,Python 3安裝中也包含這個工具。但在3.6及以上版本中,python -m venv纔是正確的選擇。

在上面的例子中,這個命令創建了一個名為env的目錄,該目錄包含一個類似於如下的目錄結構:

├── bin

│ ├── activate│ ├── activate.csh

│ ├── activate.fish

│ ├── easy_install│ ├── easy_install-3.5│ ├── pip│ ├── pip3│ ├── pip3.5│ ├── python -> python3.5│ ├── python3 -> python3.5│ └── python3.5 -> /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5├── include

├── lib

│ └── python3.5│ └── site-packages└── pyvenv.cfg

以下是每個文件夾包含的內容:

  • bin:與虛擬環境交互的文件
  • include:編譯Python包的C頭文件
  • lib: Python版本的副本,以及安裝每個依賴項的site-packages文件夾

此外,還有一些不同Python工具以及Python可執行文件本身的副本或符號鏈接。這些文件用於確保所有Python代碼和命令都在當前環境的上下文中執行,這就是如何實現與全局環境的隔離。我們將在下一節詳細解釋這一點。

更有趣的是bin目錄中的激活腳本。這些腳本用於設置shell以默認使用環境的Python可執行文件及其站點包。

為了單獨使用這個環境的包/資源,您需要「激活」它。要做到這一點,只需運行以下命令:

$ source env/bin/activate
(env) $

注意您的提示符現在如何以您的環境名(在我們的示例中是env)作為前綴。這是env當前處於活動狀態的指示器,這意味著python可執行文件將只使用該環境的包和設置。

要顯示實際的包隔離,我們可以使用bcrypt模塊作為示例。假設我們在系統範圍內安裝了bcrypt,但是沒有在虛擬環境中安裝。

在我們測試這個之前,我們需要通過執行deactivate回到「系統」上下文:

(env) $ deactivate
$

現在您的shell會話已經恢復正常,python命令引用了全局python安裝。當您使用特定的虛擬環境時,請記住這樣做。

現在,安裝bcrypt並使用它來散列密碼:

$ pip -q install bcrypt
$ python -c "import bcrypt; print(bcrypt.hashpw(password.encode(utf-8), bcrypt.gensalt()))"
$2b$12$vWa/VSvxxyQ9d.WGgVTdrell515Ctux36LCga8nM5QTW0.4w8TXXi

如果我們在激活虛擬環境時嘗試相同的命令,會發生以下情況:

$ source env/bin/activate
(env) $ python -c "import bcrypt; print(bcrypt.hashpw(password.encode(utf-8), bcrypt.gensalt()))"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named bcrypt

如您所見,python -c「import bcrypt…」命令的行為在源env/bin/activate調用之後發生了變化。

在一個例子中,我們可以使用bcrypt,而在另一個例子中我們不能。這是我們希望通過虛擬環境實現的分離,現在很容易實現。

虛擬環境如何工作?

「激活」一個環境到底意味著什麼?對於開發人員來說,瞭解底層的情況是非常重要的,特別是當您需要了解執行環境、依賴性解決方案等等時。

為瞭解釋這是如何工作的,讓我們首先查看不同python可執行程序的位置。當環境「停用」時,運行以下命令:

$ which python
/usr/bin/python

現在,激活它,再次運行命令:

$ source env/bin/activate
(env) $ which python
/Users/michaelherman/python-virtual-environments/env/bin/python

在激活環境之後,我們現在為python可執行文件獲得了不同的路徑,因為在活動環境中,$ path環境變數稍微修改了一些。

注意$ path中第一個路徑在激活前後的區別:

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:

$ source env/bin/activate
(env) $ echo $PATH
/Users/michaelherman/python-virtual-environments/env/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:

在後一個示例中,虛擬環境的bin目錄現在位於路徑的開頭。這意味著它是在命令行上運行可執行文件時搜索的第一個目錄。因此,shell使用我們的虛擬環境的Python實例,而不是系統範圍的版本。

這就提出了以下問題:

  • 這兩個可執行文件有什麼不同?
  • 虛擬環境的Python可執行文件如何能夠使用系統站點包之外的其他東西?

這可以通過Python如何啟動以及它在系統中的位置來解釋。實際上,這兩個Python可執行文件之間沒有任何區別。重要的是它們的目錄位置。

當Python啟動時,它會查看二進位文件的路徑。在虛擬環境中,它實際上只是系統Python二進位文件的副本或符號鏈接。然後設置sys的位置。前綴和系統。基於這個位置的exec_prefix,省略了路徑的bin部分。

位於sys中的路徑。然後使用前綴通過搜索相對路徑庫/pythonX來定位站點包目錄。X /網站/ X。X是您正在使用的Python版本。

在我們的例子中,二進位文件位於/Users/michaelherman/python-virtual-environments/env/bin,即sys。前綴是/Users/michaelherman/python-virtual-environments/env,因此使用的站點包目錄是/Users/michaelherman/python-virtual-environments/env/lib/pythonX.X/site-packages。最後,該路徑存儲在sys中。路徑數組,其中包含包可以駐留的所有位置

使用virtualenvwrapper管理虛擬環境

雖然虛擬環境確實解決了包管理的一些大問題,但它們並不完美。在創建了一些環境之後,您將開始看到它們創建了一些自己的問題,其中大部分都圍繞著管理環境本身。為此,創建了virtualenvwrapper工具。它只是圍繞主要的virtualenv工具的一些包裝腳本

virtualenvwrapper的一些更有用的特性是:

  • 在一個位置組織所有虛擬環境
  • 提供幫助您輕鬆創建、刪除和複製環境的方法
  • 提供在環境之間切換的單個命令

雖然其中一些功能可能看起來很小或者不重要,但是您很快就會發現它們是添加到您的工作流中的重要工具。

首先,您可以使用pip下載包裝器:

$ pip install virtualenvwrapper

一旦安裝完畢,我們需要激活它的shell函數。我們可以通過在安裝的virtualenvwrapper上運行源代碼來實現這一點。sh腳本。當您第一次使用pip安裝它時,安裝的輸出將告訴您virtualenvwrap .sh的準確位置。或者您可以簡單地運行以下命令:

$ which virtualenvwrapper.sh
/usr/local/bin/virtualenvwrapper.sh

使用該路徑,將以下三行添加到shell的啟動文件中。如果您正在使用Bash shell,您可以將這些行放在~/中。bashrc文件或~/。概要文件。對於其他shell,如zsh、csh或fish,您需要使用特定於該shell的啟動文件。重要的是,這些命令是在您登錄或打開新shell時執行的:

export WORKON_HOME=$HOME/.virtualenvs # Optional
export PROJECT_HOME=$HOME/projects # Optional
source /usr/local/bin/virtualenvwrapper.sh

最後,重新載入啟動文件:

$ source ~/.bashrc

現在應該有一個位於$WORKON_HOME的目錄,其中包含所有的virtualenvwrapper數據/文件:

$ echo $WORKON_HOME
/Users/michaelherman/.virtualenvs

您現在還可以使用shell命令來幫助管理環境。以下是一些可供選擇的方法:

  • workon
  • mkvirtualenv
  • cdvirtualenv
  • rmvirtualenv

有關命令、安裝和配置virtualenvwrapper的更多信息,請參閱文檔。

現在,任何時候你想開始一個新項目,你只需要這樣做:

$ mkvirtualenv my-new-project
(my-new-project) $

這將在$WORKON_HOME目錄中創建並激活一個新環境,所有虛擬環境都存儲在該目錄中。

要停止使用該環境,您只需要像以前一樣停用它:

(my-new-project) $ deactivate
$

如果您有許多環境可供選擇,您可以列出所有與workon功能:

$ workon
my-new-project
my-django-project
web-scraper

最後,這裡是如何激活:

$ workon web-scraper
(web-scraper) $

如果您希望能夠使用單個工具並在Python版本之間切換,那麼virtualenv將允許您這樣做。virtualenv有一個參數-p,它允許您選擇要使用的Python版本。將它與which命令結合起來,我們就可以輕鬆地選擇您喜歡的Python版本,以便以一種簡單的方式使用。例如,假設我們想要Python 3作為我們的首選版本:

$ virtualenv -p $(which python3) blog_virtualenv

這將創建一個新的Python 3環境。

它是如何工作的?

用於在$PATH變數中查找給定命令並返回該命令的完整路徑的命令。因此,返回到python3的完整路徑到-p參數,該參數接受PYTHON_EXE。這也可以用於python2。只需將python3替換為python2(或者如果系統默認為python2,則使用python)。

現在您不必記住在哪裡安裝了環境。您可以按照自己的意願輕鬆地刪除或複製它們,而且您的項目目錄也不會那麼混亂!

使用不同版本的Python

與舊的virtualenv工具不同,pyvenv不支持使用Python的任意版本創建環境,這意味著您必須為創建的所有環境使用Python 3的默認安裝。雖然您可以將環境升級到Python的最新系統版本(通過——upgrade選項),但如果環境發生了更改,您仍然不能實際指定特定的版本。

有很多方法可以安裝Python,但是很少有足夠簡單或足夠靈活的方法可以頻繁地卸載和重新安裝不同版本的二進位文件。

這就是pyenv上場的原因。

儘管名稱很相似(pyvenv vs pyenv),但pyenv不同之處在於它的重點是幫助您在系統級和項目級之間切換Python版本。pyvenv的目的是分離模塊,而pyenv的目的是分離Python版本。

你可以從安裝pyenv開始使用自製程序(在OS X上)或pyenv-installer項目:

Homebrew

$ brew install pyenv

pyenv-installer

$ curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash

一旦在系統上安裝了pyenv,下面是一些您可能感興趣的基本命令:

$ pyenv install 3.5.0 # Install new version
$ pyenv versions # List installed versions
$ pyenv exec python -V # Execute python -V using pyenv version

在這幾行中,我們安裝了Python的3.5.0版本,要求pyenv向我們顯示所有可用的版本,然後使用pyenv指定的版本執行Python -V命令。

為了給您更多的控制權,您可以使用任何可用的版本來「全局」使用或「本地」使用。使用帶有本地命令的pyenv將版本號存儲在本地. Python版本文件中,從而為特定項目或目錄設置Python版本。我們可以這樣設置「local」版本:

$ pyenv local 2.7.11

這將在當前目錄中創建.python版本的文件,如下所示:

$ ls -la
total 16
drwxr-xr-x 4 michaelherman staff 136 Feb 22 10:57 .
drwxr-xr-x 9 michaelherman staff 306 Jan 27 20:55 ..
-rw-r--r-- 1 michaelherman staff 7 Feb 22 10:57 .python-version
-rw-r--r-- 1 michaelherman staff 52 Jan 28 17:20 main.py

此文件僅包含「2.7.11」內容。現在,當您使用pyenv執行腳本時,它將載入這個文件並使用指定的版本,假設它是有效的並且存在於您的系統中。

繼續我們的示例,假設我們有一個名為main的簡單腳本。項目目錄中的py是這樣的:

import sys
print(Using version:, sys.version[:5])

它所做的就是列印出正在使用的Python可執行文件的版本號。使用pyenv和exec命令,我們可以使用已安裝的Python的任何不同版本運行腳本。

$ python main.py
Using version: 2.7.5
$ pyenv global 3.5.0
$ pyenv exec python main.py
Using version: 3.5.0
$ pyenv local 2.7.11
$ pyenv exec python main.py
Using version: 2.7.11

注意pyenv是如何執行python main的。在默認情況下,py使用的是我們的「全局」Python版本,但是在為當前目錄設置了一個版本之後,它使用的是「本地」版本。

對於那些擁有許多不同版本需求的項目的開發人員來說,這是非常強大的。您不僅可以輕鬆更改所有項目的默認版本(通過全局),還可以覆蓋它來指定特殊情況。

結論

在本文中,您不僅瞭解瞭如何存儲和解析Python依賴項,還瞭解瞭如何使用不同的社區工具來幫助解決各種打包和版本控制問題。

正如您所看到的,多虧了龐大的Python社區,您可以使用許多工具來幫助解決這些常見問題。當您作為開發人員取得進展時,一定要花時間學習如何利用這些工具。您甚至可能發現它們的非預期用途,或者學習將類似的概念應用到您使用的其他語言中。

我整理了Python的相關學習視頻及學習路線圖。
需要資料的,私信【學習】獲取更多資料 或者
加我聯繫方式: 925916955 不知道怎麼學習的人,可以來問問我,也許能夠幫助你


推薦閱讀:
相關文章