天天看點

virtualenv詳解

轉自:https://virtualenv-chinese-docs.readthedocs.org/en/latest/#

Contents

  • virtualenv
    • 安裝
    • 用處
      • 指令
      • 環境變量和配置檔案
      • Windows下注意事項
      • PyPy支援
    • 建立自己的啟動腳本
      • 啟動腳本範例
      • 激活腳本
      • --system-site-packages

         參數
      • 不使用Virtualenv下的 

        bin/python

      • 重定位隔離環境
      • --extra-search-dir

         參數
    • 與可替代品的比較
    • 貢獻力量
      • 運作測試
    • 相關文檔和連結
    • 現狀和許可
    • Wrongway的補充:常用見法
      • 1.建立隔離環境并安裝最新的django
      • 2.建立隔離環境并安裝django1.3以及一系列開發用元件
      • 3.建立Python2.7隔離環境并安裝tornado
    • Wrongway的補充:中譯版緻謝
  • Changes & News

安裝

運作 

pip install virtualenv

 即可安裝virtualenv,想用 最新開發版 就運作 

pip install virtualenv==dev

 。

還可以用 

easy_install

 安裝,即使是沒有安裝任何Python包管理器,也可以直接擷取 virtualenv.py 并運作 

python virtualenv.py

 ,效果一樣。

用處

virtualenv

 用來建立隔離的Python環境。

處理python環境的多版本和子產品依賴,以及相應的權限是一個很常見的問題。比如,你有個應用使用的是LibFoo V1.0,但另一個應用卻要用到LibFoo V2.0。 如何處理呢?如果把所有子產品都安裝到 

/usr/lib/python2.7/site-packages

 (或是你本機python預設的子產品安裝目錄),那你極有可能無意中更新一些不該更新的子產品。

更普遍的是,就算你成功安裝了某個應用,那麼接下來又會怎樣?隻要它開始運作了,那麼隻要其所依賴的子產品發生任何改動,亦或更新,都可能打斷該應用。

這還沒完,要是你無法在 

site-packages

 目錄下安裝子產品呢?比如共享主機。

上述這幾種場合都适用 

virtualenv

 。它會建立一個擁有獨立安裝目錄的python環境,該隔離環境不會與其他virtualenv環境共享子產品(可選擇是否通路全局庫目錄)。

一般用法是:

$ python virtualenv.py ENV
      

在已安裝virtualenv的情況下,可以直接運作 

virtualenv ENV

 。

該操作會建立 

ENV/lib/pythonX.X/site-packages

 目錄 和 

ENV/bin/python

 , 前者用來存放要安裝的子產品,後者就是隔離環境的Python解釋器。 在virtualenv環境下使用此解釋器(包括以 

#!/path/to/ENV/bin/python

 開頭的腳本)時,使用的都是隔離環境下的子產品。

該操作還在隔離環境下安裝了 Setuptools 或 distribute 。要用Distribue取代setuptools的話,隻要運作:

$ python virtualenv.py --distribute ENV
      

設定環境變量 VIRTUALENV_USE_DISTRIBUTE 也能達到同樣目的。

新的virtualenv還包含了 pip 包管理器,可以直接用 

ENV/bin/pip

 安裝第三方子產品。

指令

用法:

$ virtualenv [OPTIONS] DEST_DIR
      

選項:

--version

顯示目前版本号。

-h, --help

顯示幫助資訊。

-v, --verbose

顯示詳細資訊。

-q, --quiet

不顯示詳細資訊。

-p PYTHON_EXE, --python=PYTHON_EXE

指定所用的python解析器的版本,比如 

--python=python2.5

 就使用2.5版本的解析器建立新的隔離環境。 預設使用的是目前系統安裝(/usr/bin/python)的python解析器

--clear

清空非root使用者的安裝,并重頭開始建立隔離環境。

--no-site-packages

令隔離環境不能通路系統全局的site-packages目錄。

--system-site-packages

令隔離環境可以通路系統全局的site-packages目錄。

--unzip-setuptools

安裝時解壓Setuptools或Distribute

--relocatable

重定位某個已存在的隔離環境。使用該選項将修正腳本并令所有.pth檔案使用相當路徑。

--distribute

使用Distribute代替Setuptools,也可設定環境變量VIRTUALENV_DISTRIBUTE達到同樣效要。

--extra-search-dir=SEARCH_DIRS

用于查找setuptools/distribute/pip釋出包的目錄。可以添加任意數量的–extra-search-dir路徑。

--never-download

禁止從網上下載下傳任何資料。此時,如果在本地搜尋釋出包失敗,virtualenv就會報錯。

--prompt==PROMPT

定義隔離環境的指令行字首。

環境變量和配置檔案

virtualenv既可以通過指令行配置,比如 

--distribute

 ,也可以用下面兩種方式配置:

  • 環境變量

    指令行的每個參數都以 

    VIRTUALENV_<UPPER_NAME>

     的格式對應一個環境變量。 轉換變量名過程中,除了将指令行參數大寫外,還要把 (

    '-'

    ) 替換為 (

    '_'

    ) 。

    舉個例子,要自動安裝Distribute取代預設的setuptools,可以這樣設定環境變量:

    $ export VIRTUALENV_USE_DISTRIBUTE=true
    $ python virtualenv.py ENV
          
    等同于在指令行直接使用參數:
    $ python virtualenv.py --distribute ENV
          
    有時要重複輸入多個指令行參數,比如 

    --extra-search-dir

     。變成環境變量時,要用空格隔開多個參數值,例如:
    $ export VIRTUALENV_EXTRA_SEARCH_DIR="/path/to/dists /path/to/other/dists"
    $ virtualenv ENV
          
    等同于:
    $ python virtualenv.py --extra-search-dir=/path/to/dists --extra-search-dir=/path/to/other/dists ENV
          
  • 配置檔案

    virtualenv還能通過标準ini檔案進行配置。在Unix和Mac OS X中是 

    $HOME/.virtualenv/virtualenv.ini

     ,在Windows下是 

    %HOME%\\virtualenv\\virtualenv.ini

     。

    配置項名稱就是指令行參數的名稱。例如,參數 

    --distribute

     在ini檔案如下:
    [virtualenv]
    distribute = true
          
    象 

    --extra-search-dir

     這樣的多值指令行參數,在ini檔案中要用斷行将多個值隔開:
    [virtualenv]
    extra-search-dir =
        /path/to/dists
        /path/to/other/dists
          

virtualenv --help

 可以檢視完整的參數清單。

Windows下注意事項

在Windows下路徑會與*nix下略有不同:腳本和可執行檔案在Windows下位于 

ENV\Scripts\

 下,而非 

ENV/bin/

 , 子產品也會安裝在 

ENV\Lib\

 下,而非 

ENV/lib/

 。

要在某個含有空格的目錄下面建立virtualenv環境,就要安裝 win32api 。

PyPy支援

從1.5版開始,virtualenv開始支援 PyPy 。 >=1.5版的virtualenv支援PyPy1.4和1.4.1, >=1.6.1版的virtualenv支援PyPy1,5。

建立自己的啟動腳本

Wrongway提示:該段一般情況下初學者用不到,是以剛接觸virtualenv的朋友不要在此節投放過多精力。Virtualenv的文檔講解順序是有點問題。

建立隔離環境時,virtualenv不會執行額外操作。但開發者有時會想在安裝隔離環境後運作某個腳本。例如用腳本安裝某個web應用。

要建立上述腳本,需要調用 

virtualenv.create_bootstrap_script(extra_text)

 ,将後續操作寫入到生成的啟動腳本,以下是從docstring中生成的文檔:

啟動腳本與一般腳本無異,隻是多了三個extend_parser, adjust_options, after_install三個鈎子方法。

create_bootstrap_script傳回一個可定制的,能做為啟動腳本的字元串(當然,該字元串後面要寫回到磁盤檔案中)。 這個字元串是一個标準的virtualenv.py腳本,使用者可以自行添加内容(所加内容必須是python代碼)。

如果定義了下列方法,運作腳本時就會被調用:

extend_parser(optparse_parser)

:
可以在解析器optparse_parser中添加或删除參數。

adjust_options(options, args)

:
調整options,或改變args(如果要接收各種不同的參數,一定要在最後将 

args

 修改為 

[DEST_DIR]

 )

after_install(options, home_dir)

:
在所有代碼和子產品安裝完之後,就會調用該方法。這可能是使用者最喜歡的方法,例如下:
def after_install(options, home_dir):
    if sys.platform == 'win32':
        bin = 'Scripts'
    else:
        bin = 'bin'
    subprocess.call([join(home_dir, bin, 'easy_install'),
                     'MyPackage'])
    subprocess.call([join(home_dir, bin, 'my-package-script'),
                     'setup', home_dir])
      
上述例子會安裝一個包,并運作包内的setup腳本

wrongway在這裡強調:上述三個方法并不是獨立方法,而是一段代碼字元串!!也就是extra_text的内容。有點象javascript下的 eval(‘......代碼字元串......’)

啟動腳本範例

這有個具體的例子:

import virtualenv, textwrap
output = virtualenv.create_bootstrap_script(textwrap.dedent("""
import os, subprocess
def after_install(options, home_dir):
    etc = join(home_dir, 'etc')
    if not os.path.exists(etc):
        os.makedirs(etc)
    subprocess.call([join(home_dir, 'bin', 'easy_install'),
                     'BlogApplication'])
    subprocess.call([join(home_dir, 'bin', 'paster'),
                     'make-config', 'BlogApplication',
                     join(etc, 'blog.ini')])
    subprocess.call([join(home_dir, 'bin', 'paster'),
                     'setup-app', join(etc, 'blog.ini')])
"""))
f = open('blog-bootstrap.py', 'w').write(output)
      

這還有一個例子 點選 。

激活腳本

剛建立的隔離環境下會有一個 

bin/activate

 指令行腳本。在Windows下,激活腳本要在CMD.exe或Powershell.exe中使用。

在Posix系統(*nix/BSD)中,用法如下:

$ source bin/activate
      

該操作會将目前 

$PATH

 指向隔離環境下的 

bin/

 目錄。之是以要用source是因為它要改變目前shell環境。僅僅就是一行指令,就這麼簡單。 如果直接運作隔離環境下的腳本或是python解釋器(比如 

path/to/env/bin/pip

 or

/path/to/env/bin/python script.py

 ),那都沒必要使用激活腳本。

輸入 

deactivate

 就能退出已激活的隔離環境,也就是取消對目前 

$PATH

 所做的修改。

activate

 腳本會修改目前shell指令行提示符,以提示目前激活的是哪個隔離環境。這是挺有用的, 不過要是想自定義的提示符,隻要在運作 

activate

 前将 

VIRTUAL_ENV_DISABLE_PROMPT

 設為你想要的提示(不能為空字元串)。

在Windows下隻須如此(*nix使用者此處就不用看了,包括下面的注意也不用看了):

> \path\to\env\Scripts\activate
      

輸入 deactivate 就能退出隔離環境。

視你用的shell不同(CMD.exe或Powershell.exe),Windows會使用activate.bat或activate.ps1來激活隔離環境。 如果使用的是Powershell,那麼以下幾點值得注意。

注意(說真的,開發python還是在*nix下好,真的真的真的!):

使用Powershell時,運作 ``activate`` 腳本取決于`執行政策`_ 。但在Windows7下,預設情況下執行政策被設為嚴格,
這就意味着象 ``activate`` 這樣的腳本是不能直接運作的。但稍微設定一下即可。

降低執行政策,改為 ``AllSigned``, 這就意味着本機所有已認證數字簽名的腳本都獲許運作。
由于virtualenv作者之一Jannis Leidel的數字簽名已被核準,允許運作。那麼隻要以管理者權限運作::

    PS C:\> Set-ExecutionPolicy AllSigned

接下來運作腳本時會提示是否信任該簽名::

    PS C:\> virtualenv .\foo
    New python executable in C:\foo\Scripts\python.exe
    Installing setuptools................done.
    Installing pip...................done.
    PS C:\> .\foo\scripts\activate

    Do you want to run software from this untrusted publisher?
    File C:\foo\scripts\activate.ps1 is published by [email protected],
    CN=Jannis Leidel, L=Berlin, S=Berlin, C=DE, Description=581796-Gh7xfJxkxQSIO4E0
    and is not trusted on your system. Only run scripts from trusted publishers.
    [V] Never run  [D] Do not run  [R] Run once  [A] Always run  [?] Help
    (default is "D"):A
    (foo) PS C:\>

如果選擇了 ``[A] Always Run``, 該證書就會添加到目前帳戶下的受信任釋出者名單中,而且此後一直被該使用者所信任。
如果選擇了 ``[R] Run Once``, 該腳本會立即運作,但之後每次使用都會重新出現信任提示并選擇。
進階使用者可以将該證書添加到目前計算機的受信任釋出者名單中,這樣所有使用者都可以使用該腳本了(不過這部分内容已經超過了本文檔範疇了)。

此外,還可以進一步降低執行政策,允行未驗證的本地腳本運作::

    PS C:\> Set-ExecutionPolicy RemoteSigned

因為對任何一個virtualenv環境而言, ``activate.ps1`` 都是一個本地腳本而非遠端腳本,因為可以獲準運作。
      

--system-site-packages

 參數

virtualenv --system-site-packages ENV

 建立的隔離環境能直接引用 

/usr/lib/python2.7/site-packages

 (即是本機全局site-packages路徑)中的子產品。

隻在擁有全局site-packages目錄的讀寫權限,并且你的應用要依賴其中的子產品的情況下,該參數會很有用。其他情況下沒必要使用該參數。

不使用Virtualenv下的 

bin/python

某些情況下,我們無法或是不想使用由virtualenv建立的Python解釋器。 比如,在 mod_python 或 mod_wsgi 下,隻能用唯一一個Python解釋器。(wrongway補充,不過uwsgi是可以使用多個python解釋器的)

幸運的是,這相當簡單。隻要用指定的Python解釋器來 安裝 應用包即可。 但要使用這些子產品,就得更正路徑。有一個腳本可以用來更正路徑,如下這般設定環境:

activate_this = '/path/to/env/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))
      

上述操作會更改 

sys.path

 和 

sys.prefix

 ,但使用的仍是目前Python解釋器。在隔離環境中 會先尋找 

sys.path

 下的内容再尋找全局路徑。不過全局路徑始終是可以通路的(無論隔離環境是否是由 

--system-site-packages

 建立的)。 而且,上述操作不會影響其他隔離環境,也不會更正在此之前已經引用的子產品。是以,在處理web請求時才激活環境往往是無效的,應該盡可能早的激活環境和更正路徑,而不是在處理請求時才開始處理。

重定位隔離環境

注意: –relocatable參數帶有一定的實驗性,可能還有一些尚未發現的問題。而且該參數也不能在Windows下使用。

一般情況下,隔離環境都綁定在某個特定路徑下。這也就意味着不能通過僅僅是移動或拷貝目錄到另一台計算機上而遷移隔離環境。 這時可以使用–relocatable來重定位隔離環境:

$ virtualenv --relocatable ENV
      

該參數會根據相對路徑生成某些setuptools或distribute檔案,然後再運作 

activate_this.py

 更改所有的腳本, 而不是通過改變python解釋器軟連結的指向來重置環境。

注意: 安裝 任何 包之後,都要再次重定位環境。隻要你将某個隔離環境遷移了,那麼每安裝一個新的包之後,都要再運作一遍 

virtualenv --relocatable

 。

要認識到,該參數 不能做到真正的跨平台 。雖然我們可以移動相關目錄,但僅僅能用于類似的計算機之間。 一些已知的環境差異,仍會導緻不相容:

  • 不同版本的Python
  • 不同平台使用不同的内部編碼,比如一台用UCS2,另一台用UCS4
  • Linux和Windows
  • Intel和ARM
  • 某些包依賴系統的C庫,而C庫在不同平台下有所差異(不同的版本或不同的檔案系統下的所在位置)。

使用重定位參數建立新隔離環境時,會預設使用 

--system-site-packages

 參數。

--extra-search-dir

 參數

建立新的隔離環境時,virtualenv會安裝setuptools,distribute或是pip包管理器。一般情況下, 它們都會從 Python Package Index (PyPI) 中尋找并安裝最新的包。但在一些特定情況下,我們并不希望如此。例如, 你在部署virtualenv時既不想從網上下載下傳,也不想從PyPI中擷取包。

做為替代方案,可以讓setuptools,distribute或是pip搜尋檔案系統,讓virtualenv使用本地發行包而不是從網上下載下傳。 隻要象下面這樣傳入一個或多個 

--extra-search-dir

 參數就能使用該特性:

$ virtualenv --extra-search-dir=/path/to/distributions ENV
      

/path/to/distributions

 路徑指向某個包含setuptools/distribute/pip發行包的目錄。 Setuptools發行包必須是 

.egg

 檔案,distribute和pip發行包則是 .tar.gz 原代碼壓縮包。

如果本地路徑沒有找到相應的釋出包,virtualenv還是會從網上下載下傳。

要想確定不會從網上下載下傳任何發行包,就使用 

--never-download

 參數,如下:

$ virtualenv --extra-search-dir=/path/to/distributions --never-download ENV
      

這樣,virtualenv不會從網上下載下傳任何發行包。而隻搜尋本地發行包,如果沒有找到要安裝的包,就傳回狀态碼1。 virtualenv會按照如下順序搜尋發行包位置:

  1. 目前目錄
  2. virtualenv.py所在目錄
  3. virtualenv.py所在目錄下的 

    virtualenv_support

     目錄
  4. 如果實際運作的腳本名并不是virtualenv.py (換句話說,就是你的自定義啟動腳本 ),會搜尋實際安裝的virtualenv.py所在目錄下的``virtualenv_support`` 目錄。

與可替代品的比較

下面幾個替代品也可以建立隔離環境:

  • workingenv

     (建議不考慮workingenv) 是virtualenv的前身。它使用全局環境的Python解釋器, 但要靠設定 

    $PYTHONPATH

     來激活環境。是以在運作隔離環境以外的Python腳本時,出現很多問題 (比如,象全局環境下的 

    hg

     或 

    bzr

     )。而且它與Setuptools也有很多沖突。
  • virtual-python 也是virtualenv的前身。它隻使用軟連結,是以不能在Windows上工作。而且它的連結會覆寫 标準子產品和全局環境的 

    site-packages

     ,是以無法使用安裝在全局環境下的 

    site-packages

     的第三方子產品

    因為virtual-python的軟連結隻是覆寫了全局環境下的标準子產品的一部分, 是以在windows上,可以用拷貝子產品檔案的方式來使用virtual-python。 同時,它會建立一個空的 

    site-packages

     ,并把全局環境的 

    site-packages

     指向該目錄,是以更新是分别跟蹤記錄的(這塊wrongway也不了解是什麼意思,或許作者是想說要兩個目錄都注意要更新吧)。 virtual-python也會自動安裝Setuptools,進而省去了從網上手動安裝這一步。
  • zc.buildout 不會以上述方式建立隔離的Python環境, 但它通過定義配置檔案,使用非常特殊的子產品,配置腳本達到了相似的效果。做為一個可定義的系統, 它是非常容易複制和管理的,但是比較難以改寫。 

    zc.buildout

     可以安裝非Python的系統(比如資料庫伺服器或是Apache執行個體)

我 強烈 建議任何人開發或部署應用時都應該上述工具中的某一款

貢獻力量

參照 contributing to pip (參與PIP貢獻)這篇文章,裡面提及的内容同樣适用于virtualenv。

Virtualenv與pip同步發行,每有新的pip釋出,就意味着該捆綁新版本pip的virtualenv也釋出了。

運作測試

Virtualenv 的測試案例很小,也不完整,但我們後面會完善的。

運作測試的最簡單方法就是(自動處理測試依賴):

$ python setup.py test
      

可以使用nose運作測試的某一部分。建立一個virtualenv環境,然後安裝必要的包:

$ pip install nose mock
      

運作nosetests:

$ nosetests
      

或是隻測試某個檔案:

$ nosetests tests.test_virtualenv
      

相關文檔和連結

  • James Gardner 編寫了教程, 在virtualenv下使用Pylons 。
  • 博文 workingenv已死,virtualenv當立 。
  • Doug Hellmann 介紹了 virtualenv(virtualenvwrapper)指令行下流水線運作 , 通過幾個自寫的腳本,讓運作多個環境變得更加容易。 他還寫了 在virtualenv下運作IPython 。
  • Chris Perkins 在showmedo創作了視訊 使用virtualenv 。
  • 在mod_wsgi下使用virtualenv 。
  • 更多virtualenv周邊工具 。

現狀和許可

virtualenv

 是 workingenv 的更新, 也是 virtual-python 的擴充。

virtualenv

 由 Ian Bicking 編寫,接受 Open Planning Project 贊助,由 開發小組 負責維護。 該開源遵循 MIT 協定。

Wrongway的補充:常用見法

1.建立隔離環境并安裝最新的django

使用目前系統預設Python解釋器安裝最新的django(目前是1.4),以及django用到的mysql驅動:
$ mkdir myproject1
$ cd myproject1
$ virtualenv env --no-site-packages
$ source env/bin/active
$(env) pip install django
$(env) pip install mysql-python
$(env) deactive
$
      

2.建立隔離環境并安裝django1.3以及一系列開發用元件

首先編輯一個.pip檔案,假定為requirement.pip檔案,将要用到的第三方子產品名稱寫入:
Django==1.3
PIL
South
sorl-thumbnail
pylibmc
mysql-python
django-debug-toolbar
      
再在指令行運作:
$ mkdir myproject2
$ cd myproject2
$ virtualenv environ --no-site-packages
$ source environ/bin/active
$(environ) pip install -r requirement.pip
$(environ) deactive
$
      

3.建立Python2.7隔離環境并安裝tornado

我目前環境的預設Python解析器版本是2.6,我已經安裝了python2.7,現在兩個python共存,但預設使用還是2.6:
$ mkdir myproject3
$ cd myproject3
$ virtualenv huanjing --no-site-packages --python=python2.7
$ source huanjing/bin/active
$(huanjing) pip install tornado
$(huanjing) deactive
$
      
要注意的,python2.7應該是被已設為全局可通路的,在目前指令行輸入python2.7是可運作的,否則–python就要設為python2.7解釋器的完整路徑。

Wrongway的補充:中譯版緻謝

首先感謝我的妻,由于我受限于英文水準,本文很多生僻詞語句子是由外語專業的老婆翻譯和糾正的。在我譯文的同時,她也在創作她的官案懸疑小說 《大明禦史傳》 。

同時感謝扣扣群60158309的熱心pythoner,有你們的鼓勵,我才重新拾起翻譯。