首頁 > 軟體

Python虛擬環境工具-Virtualenv 介紹及部署記錄

2020-06-16 16:40:34

在開發Python應用程式時,系統預設的Python版本可能會不相容這個應用程式, 如果同時開發多個應用程式, 可能會用到好幾個版本的python環境, 這種情況下,每個應用可能需要各自擁有一套"獨立"的Python執行環境。virtualenv就是用來為一個應用建立一套"隔離"的Python執行環境的工具。virtualenv是python的一個虛擬化環境工具,用來建立一個虛擬的python環境,一個專屬於專案的python環境, 用virtualenv 來保持一個乾淨的環境非常有用, 可以幫助我們在同一台host上建立多套純淨的python直譯器環境並實現相互隔離,各個環境下安裝的庫僅限於自己的環境,不會影響到別人。

動態語言Ruby、Python都有自己的虛擬環境,虛擬環境是程式執行時的獨立執行環境,在同一台伺服器中可以建立不同的虛擬環境供不同的系統使用,專案之間的執行環境保持獨立性而相互不受影響。例如專案A在基於Python2的環境中執行,而專案B可以在基於Python3的環境中執行。Python通virtualenv工具管理虛擬環境。

簡而言之, Virtualenv是一個建立隔絕的Python環境的工具。virtualenv建立一個包含所有必要的可執行檔案的資料夾,用來使用Python工程所需的包。Virtualenv用於建立獨立的Python環境,多個Python相互獨立,互不影響,它能夠幫助:
-  在沒有許可權的情況下安裝新套件;
-  不同應用可以使用不同的套件版本;
-  套件升級不影響其他應用。
-  隔離專案之間的第三方包依賴
-  在沒有許可權的情況下安裝新的Python軟體包
-  還有一個額外的好處:部署應用時,把開發環境的虛擬環境打包到生產環境即可。

virtualenv 安裝

[root@kevin-test ~]# cat /etc/RedHat-release    (本文是在CentOS7下操作並驗證無誤)
CentOS Linux release 7.5.1804 (Core)
 
[root@kevin-test ~]# python -V
Python 2.7.5
 
[root@kevin-test ~]# pip -V
-bash: pip: command not found
 
先來安裝pip
[root@kevin-test ~]# yum -y install epel-release
[root@kevin-test ~]# yum install python-pip
[root@kevin-test ~]# pip install --upgrade pip
[root@kevin-test ~]# pip -V
pip 18.1 from /usr/lib/python2.7/site-packages/pip (python 2.7)
 
通過pip安裝virtualenv
[root@kevin-test ~]# pip install virtualenv
Collecting virtualenv
  Downloading https://files.pythonhosted.org/packages/7c/17/9b7b6cddfd255388b58c61e25b091047f6814183e1d63741c8df8dcd65a2/virtualenv-16.1.0-py2.py3-none-any.whl (1.9MB)
    100% |████████████████████████████████| 1.9MB 1.3MB/s
Installing collected packages: virtualenv
Successfully installed virtualenv-16.1.0
 
測試安裝後virtualenv的版本
[root@kevin-test ~]# virtualenv  --version
16.1.0
 
檢視幫助
[root@kevin-test ~]# virtualenv --help
Usage: virtualenv [OPTIONS] DEST_DIR
 
Options:
  --version            show program's version number and exit
  -h, --help            show this help message and exit
  -v, --verbose        Increase verbosity.
  -q, --quiet          Decrease verbosity.
  -p PYTHON_EXE, --python=PYTHON_EXE
                        The Python interpreter to use, e.g.,
                        --python=python3.5 will use the python3.5 interpreter
                        to create the new environment.  The default is the
                        interpreter that virtualenv was installed with
                        (/usr/bin/python2)
  --clear              Clear out the non-root install and start from scratch.
  --no-site-packages    DEPRECATED. Retained only for backward compatibility.
                        Not having access to global site-packages is now the
                        default behavior.
  --system-site-packages
                        Give the virtual environment access to the global
                        site-packages.
  --always-copy        Always copy files rather than symlinking.
  --relocatable        Make an EXISTING virtualenv environment relocatable.
                        This fixes up scripts and makes all .pth files
                        relative.
  --no-setuptools      Do not install setuptools in the new virtualenv.
  --no-pip              Do not install pip in the new virtualenv.
  --no-wheel            Do not install wheel in the new virtualenv.
  --extra-search-dir=DIR
                        Directory to look for setuptools/pip distributions in.
                        This option can be used multiple times.
  --download            Download preinstalled packages from PyPI.
  --no-download, --never-download
                        Do not download preinstalled packages from PyPI.
  --prompt=PROMPT      Provides an alternative prompt prefix for this
                        environment.
  --setuptools          DEPRECATED. Retained only for backward compatibility.
                        This option has no effect.
  --distribute          DEPRECATED. Retained only for backward compatibility.
                        This option has no effect.
  --unzip-setuptools    DEPRECATED.  Retained only for backward compatibility.
                        This option has no effect.

virtualenv 使用

現在為某一個工程建立一個虛擬環境, 建立一個獨立的Python執行環境,命名為pj_test (這是虛擬環境目錄名,目錄名可自行自定義)
[root@kevin-test ~]# cd /opt/
[root@kevin-test opt]# mkdir project_test
[root@kevin-test opt]# cd project_test
[root@kevin-test project_test]# virtualenv --no-site-packages pj_test
New python executable in /opt/project_test/pj_test/bin/python2
Also creating executable in /opt/project_test/pj_test/bin/python
Installing setuptools, pip, wheel...
done.
 
如上命令virtualenv就可以建立一個獨立的Python執行環境,這裡還加上了引數--no-site-packages (也可以不跟這個引數),這樣已經安裝到系統Python環境
中的所有第三方包都不會複製過來,於是就得到了一個不帶任何第三方包的"乾淨"的Python執行環境。
 
上面命令將會在當前的目錄中建立一個資料夾pj_test,這個資料夾包含一些Python執行檔案,以及pip副本,用於安裝其他的packges。
虛擬環境的名字(此例中是pj_test )可以是任意的;若省略名字將會把檔案均放在當前目錄。
 
[root@kevin-test project_test]# ls
pj_test
[root@kevin-test project_test]# ls pj_test/
bin  include  lib  lib64
 
[root@kevin-test project_test]# yum install -y tree
[root@kevin-test project_test]# tree pj_test/bin   
pj_test/bin
├── activate
├── activate.csh
├── activate.fish
├── activate.ps1
├── activate_this.py
├── easy_install
├── easy_install-2.7
├── pip
├── pip2
├── pip2.7
├── python -> python2
├── python2
├── python2.7 -> python2
├── python-config
└── wheel
 
[root@kevin-test project_test]# tree pj_test/include/
pj_test/include/
└── python2.7 -> /usr/include/python2.7
 
[root@kevin-test project_test]# tree pj_test/lib| head -3
pj_test/lib
└── python2.7
    ├── _abcoll.py -> /usr/lib64/python2.7/_abcoll.py
 
新建的Python環境被放到當前目錄下的pj_test目錄。有了pj_test這個Python環境,可以用source啟用虛擬環境:
[root@kevin-test project_test]# pwd
/opt/project_test
[root@kevin-test project_test]# ls
pj_test
[root@kevin-test project_test]# cd pj_test/
[root@kevin-test pj_test]# source ./bin/activate
(pj_test) [root@kevin-test pj_test]# python -V
Python 2.7.5
 
啟用虛擬環境, 在虛擬環境裡, 任何使用pip安裝的包將會放在 venv 資料夾中,與全域性安裝或其他應用的Python環境完全隔絕開。
 
如果建立虛擬環境時不選擇指定的python版本, 那麼虛擬環境建立後預設就是系統預設的python版本.
比如如果系統還有一個python3.6.1, 路徑為: /usr/local/python3/bin/python3
[root@kevin-test pj_test]# /usr/local/python3/bin/python3 -V 
Python 3.6.1
 
則建立虛擬機器時選擇指定的python版本
[root@kevin-test project_test]# virtualenv --no-site-packages -p /usr/local/python3/bin/python3.6.1 pj_test
[root@kevin-test project_test]# cd pj_test/
[root@kevin-test pj_test]# source ./bin/activate
(pj_test) [root@kevin-test pj_test]# python -V
Python 3.6.1
 
可以在伺服器上提前安裝多個版本的python環境, 不同版本的python的二進位制路徑不一樣
然後在使用virtualenv建立各個專案的虛擬環境時指定不同的python版本, 這樣各個專案python直譯器環境就實現了??互隔離, 非常純淨!
 
使用"deactivate" 命令退出或停用虛擬環境:
[root@kevin-test project_test]# cd pj_test/
[root@kevin-test pj_test]# source ./bin/activate
(pj_test) [root@kevin-test pj_test]# python -V
Python 2.7.5
(pj_test) [root@kevin-test pj_test]# deactivate
[root@kevin-test pj_test]#
 
退出虛擬環境後, 此時就回到了正常的環境,現在pip或python均是在系統Python環境下執行。
退出虛擬環境後, 之前在虛擬環境裡的部署的應用程式的使用都不會受到影響!
完全可以針對每個應用建立獨立的Python執行環境,這樣就可以對每個應用的Python環境進行隔離。
 
如果要刪除一個虛擬環境, 只需刪除它的虛擬目錄即可, 比如要刪除虛擬環境pj_test, 則:
[root@kevin-test pj_test]#  rm -rf /opt/project_test/pj_test/

在虛擬環境安裝 Python packages

Virtualenv 附帶有pip安裝工具,因此需要安裝的packages可以直接執行:
(pj_test) [root@kevin-test pj_test]# pip install [套件名稱]
(pj_test) [root@kevin-test pj_test]# pip -V
pip 18.1 from /opt/project_test/pj_test/lib/python2.7/site-packages/pip (python 2.7)
 
(pj_test) [root@kevin-test pj_test]# pip install jinja2
 
安裝後, 可以在虛擬環境裡找到這個套件
(pj_test) [root@kevin-test pj_test]# ll -d /opt/project_test/pj_test/lib/python2.7/site-packages/jinja2/
drwxr-xr-x 2 root root 4096 Dec 17 18:26 /opt/project_test/pj_test/lib/python2.7/site-packages/jinja2/
 
在虛擬環境下,用pip安裝的包都被安裝到對應虛擬的這個環境下,系統Python環境不受任何影響。
也就是說,虛擬環境是專門針對具體的某個應用建立的。
 
[root@kevin-test ~]# pip -V
pip 18.1 from /usr/lib/python2.7/site-packages/pip (python 2.7)
 
如果沒有啟動虛擬環境,系統環境也安裝了pip工具,那麼packages將被安裝在系統環境中.
為了避免發生此事,可以在~/.bashrc檔案中加上 (最好新增下面的內容):
[root@kevin-test ~]# vim ~/.bashrc
export PIP_REQUIRE_VIRTUALENV=true
 
使設定生效
[root@kevin-test ~]# source ~/.bashrc
 
如果在沒開啟虛擬環境時, 在虛擬環境之外的系統上執行pip,就會提示錯誤:"Could not find an activated virtualenv (required)".

如上安裝好virtualenv之後, 就可以解決python版本衝突問題和python庫不同版本的問題了!!

virtualenv 用法小總結

1) 建立環境
virtualenv [新環境名] :這會再當前目錄下建立一個新環境目錄
可使用 virtualenv --help 來檢視如何使用。可以使用引數 --python=/usr/bin/python3 來建立一個已經安裝的的Python環境。
 
2) 使用環境
切換到專案的新環境目錄
執行:source ./bin/activate 來啟用環境,啟用後在命令列的前面會出現新環境名稱
接下來可使用pip命令安裝新環境需要的各種包。(pip命令在建立新環境時自帶)
 
3) 退出虛擬環境
deactivate
如果要刪除虛擬環境,只需退出虛擬環境後,刪除對應的虛擬環境目錄即可。不影響其他環境。
 
4) 注意事項
如果沒有啟動虛擬環境,系統也安裝了pip工具,那麼套件將被安裝在系統環境中,為了避免發生此事,可以在~/.bashrc檔案中加上:export PIP_REQUIRE_VIRTUALENV=true
或者讓在執行pip的時候讓系統自動開啟虛擬環境:export PIP_REQUIRE_VIRTUALENV=true
 
5) 保證環境一致性
用pip freeze檢視當前安裝版本
[root@kevin-test ~]# pip freeze
 
另外:
[root@kevin-test ~]# pip freeze > requirements.txt
這將會建立一個 requirements.txt 檔案,其中包含了當前環境中所有包及 各自的版本的簡單列表。
可以使用 "pip list"在不產生requirements檔案的情況下, 檢視已安裝包的列表。
 
這將會使另一個不同的開發者(或者是你本人,如果你本人需要重新建立這樣的環境) 在以後安裝相同版本的相同包變得容易。
將這個requirements.txt拷貝到新的機器環境下執行:
# pip install -r requirements.txt
 
這能幫助確保安裝、部署和開發者之間的一致性。

虛擬環境管理工具 - Virtualenvwrapper
virtualenv使用起來不是很方便,因為virtual的啟動、停止指令碼都在特定目錄,可能一段時間後,你可能會有很多個虛擬環境散落在系統各處,你可能忘記它們的名字或者位置。鑑於virtualenv不便於對虛擬環境集中管理,所以推薦直接使用virtualenvwrapper。 virtualenvwrapper提供了一系列命令使得和虛擬環境工作變得便利。它把你所有的虛擬環境都放在一個地方。

Virtaulenvwrapper是virtualenv的擴充套件包,用於更方便管理虛擬環境,它可以做:
-  將所有虛擬環境整合在一個目錄下;
-  管理(新增,刪除,複製)虛擬環境;
-  切換虛擬環境等等.
 
安裝virtualenvwrapper (確保virtualenv已提前安裝)
[root@kevin-test ~]# pip install virtualenvwrapper
Could not find an activated virtualenv (required).
 
如果出現上面的報錯:"Could not find an activated virtualenv (required)."
 
解決辦法:
開啟~/.bashrc檔案, 新增下面的內容
[root@kevin-test ~]# vim ~/.bashrc
export PIP_REQUIRE_VIRTUALENV=true
[root@kevin-test ~]# source ~/.bashrc
 
然後接著安裝virtualenvwrapper
[root@kevin-test ~]# pip install virtualenvwrapper
 
如果還是出現上面的那個報錯:"Could not find an activated virtualenv (required)."
 
接著執行下面命令(~/.bashrc檔案裡設定該引數為true, 確保pip安裝的包在虛擬環境下; 虛擬環境之外的系統裡執行pip時, 每次需要手動source 這個引數的false值)
[root@kevin-test ~]# export PIP_REQUIRE_VIRTUALENV=false
 
最後再次安裝virtualenvwrapper即可
[root@kevin-test ~]# pip install virtualenvwrapper     
Collecting virtualenvwrapper
  Using cached https://files.pythonhosted.org/packages/2b/8c/3192e10913ad945c0f0fcb17e9b2679434a28ad58ee31ce0104cba3b1154/virtualenvwrapper-4.8.2-py2.py3-none-any.whl
Requirement already satisfied: virtualenv-clone in /usr/lib/python2.7/site-packages/virtualenv_clone-0.4.0-py2.7.egg (from virtualenvwrapper) (0.4.0)
Requirement already satisfied: stevedore in /usr/lib/python2.7/site-packages/stevedore-1.30.0-py2.7.egg (from virtualenvwrapper) (1.30.0)
Requirement already satisfied: virtualenv in /usr/lib/python2.7/site-packages (from virtualenvwrapper) (16.1.0)
Requirement already satisfied: pbr!=2.1.0,>=2.0.0 in /usr/lib/python2.7/site-packages/pbr-5.1.1-py2.7.egg (from stevedore->virtualenvwrapper) (5.1.1)
Requirement already satisfied: six>=1.10.0 in /usr/lib/python2.7/site-packages/six-1.12.0-py2.7.egg (from stevedore->virtualenvwrapper) (1.12.0)
Installing collected packages: virtualenvwrapper
Successfully installed virtualenvwrapper-4.8.2
 
預設virtualenvwrapper安裝在下面python直譯器中的site-packages,實際上需要執行virtualenvwrapper.sh檔案才行;
所以要查詢出安裝的virtualenvwrapper.sh執行檔案
[root@kevin-test ~]# find / -name virtualenvwrapper*
/usr/bin/virtualenvwrapper.sh
/usr/bin/virtualenvwrapper_lazy.sh
/usr/lib/python2.7/site-packages/virtualenvwrapper-4.8.2-py2.7-nspkg.pth
/usr/lib/python2.7/site-packages/virtualenvwrapper
/usr/lib/python2.7/site-packages/virtualenvwrapper-4.8.2.dist-info
 
此時還不能使用virtualenvwrapper,每次要想使用virtualenvwrapper 工具時,都必須先啟用virtualenvwrapper.sh檔案才行,
另外,如果建立前要將即將的環境儲存到虛擬環境中,就要先設定一下環境變數
 
設定環境變數
[root@kevin-test ~]# export WORKON_HOME=~/Envs
 
建立虛擬環境管理目錄. 即建立的虛擬環境都會放到上面設定的~/Envs目錄下面
[root@kevin-test ~]# mkdir -p $WORKON_HOME
 
在~/.bashrc檔案裡設定環境變數, 新增下面兩行
第一行表示: 存放虛擬環境目錄
第二行表示: virtrualenvwrapper.sh執行檔案的路徑
[root@kevin-test ~]# vim ~/.bashrc
export WORKON_HOME=~/Envs
source /usr/bin/virtualenvwrapper.sh
 
使得以上環境變數的設定生效
[root@kevin-test ~]# source ~/.bashrc
 
現在開始使用Virtualenvwrapper 管理虛擬機器 (可以刪除上面之前建立的虛擬環境/opt/project_test/pj_test 了, 後續都將使用Virtualenvwrapper建立和管理虛擬環境)
 
a) 使用mkvirtualenv 命令建立虛擬環境
建立一個虛擬環境, 虛擬機器名稱為project_kevin:
[root@kevin-test ~]# mkvirtualenv project_kevin
New python executable in /root/Envs/project_kevin/bin/python2
Also creating executable in /root/Envs/project_kevin/bin/python
Installing setuptools, pip, wheel...
done.
virtualenvwrapper.user_scripts creating /root/Envs/project_kevin/bin/predeactivate
virtualenvwrapper.user_scripts creating /root/Envs/project_kevin/bin/postdeactivate
virtualenvwrapper.user_scripts creating /root/Envs/project_kevin/bin/preactivate
virtualenvwrapper.user_scripts creating /root/Envs/project_kevin/bin/postactivate
virtualenvwrapper.user_scripts creating /root/Envs/project_kevin/bin/get_env_details
(project_kevin) [root@kevin-test ~]#
 
再建立另一個虛擬機器, 虛擬機器名稱為project_bobo
(project_kevin) [root@kevin-test ~]# deactivate                                //先退出上面的那個虛擬環境
[root@kevin-test ~]# mkvirtualenv --no-site-packages project_bo      //這裡加上了引數--no-site-packages
New python executable in /root/Envs/project_bo/bin/python2
Also creating executable in /root/Envs/project_bo/bin/python
Installing setuptools, pip, wheel...
done.
virtualenvwrapper.user_scripts creating /root/Envs/project_bo/bin/predeactivate
virtualenvwrapper.user_scripts creating /root/Envs/project_bo/bin/postdeactivate
virtualenvwrapper.user_scripts creating /root/Envs/project_bo/bin/preactivate
virtualenvwrapper.user_scripts creating /root/Envs/project_bo/bin/postactivate
virtualenvwrapper.user_scripts creating /root/Envs/project_bo/bin/get_env_details
(project_bo) [root@kevin-test ~]#
 
====================================================
還可以選擇指定的python版本進行虛擬環境的建立, 不過指定的python版本必須要提前安裝好, 比如
# mkvirtualenv project_hui --python=python3.6.1
# mkvirtualenv project_hui --python=/usr/local/python3/bin/python3.6.1
====================================================
 
建立的虛擬環境的專案目錄都放在了上面設定的環境變數目錄~/Envs下面
[root@kevin-test ~]# ll -d ~/Envs/project_kevin/
drwxr-xr-x 5 root root 56 Dec 17 22:27 /root/Envs/project_kevin/
[root@kevin-test ~]# ll -d ~/Envs/project_bo/
drwxr-xr-x 5 root root 56 Dec 17 22:28 /root/Envs/project_bo/
 
b) 使用workon 或者 lsvirtualenv 命令列出虛擬環境列表
[root@kevin-test ~]# workon
project_bo
project_kevin
 
或者
[root@kevin-test ~]# lsvirtualenv
project_bo
==========
 
 
project_kevin
=============
 
c) 使用workon 啟動/切換虛擬環境
[root@kevin-test ~]# workon project_bo
(project_bo) [root@kevin-test ~]# python -V
Python 2.7.5
(project_bo) [root@kevin-test ~]#
 
建立一個專案,它會建立虛擬環境,並在 $WORKON_HOME 中建立一個專案目錄。
當您使用 "workon 專案的虛擬環境名稱" 時,它會自動cd -ed 到專案目錄中。
 
d) 使用deactivate命令退出/離開虛擬環境,和virutalenv一樣的命令
[root@kevin-test ~]# workon project_bo
(project_bo) [root@kevin-test ~]# python -V
Python 2.7.5
(project_bo) [root@kevin-test ~]# deactivate
[root@kevin-test ~]#
 
e) 使用rmvirtualenv 命令 刪除虛擬環境
[root@kevin-test ~]# lsvirtualenv   
project_bo
==========
 
 
project_kevin
=============
 
 
[root@kevin-test ~]# rmvirtualenv project_bo
Removing project_bo...
[root@kevin-test ~]# lsvirtualenv         
project_kevin
=============
 
f) 使用lssitepackages命令顯示 site-packages 目錄中的內容。
[root@kevin-test ~]# workon project_kevin       
(project_kevin) [root@kevin-test ~]# lssitepackages
easy_install.py  pip                pkg_resources  setuptools-40.6.3.dist-info  wheel-0.32.3.dist-info
easy_install.pyc  pip-18.1.dist-info  setuptools    wheel
 
g) 使用cdvirtualenv命令導航到當前啟用的虛擬環境的目錄中,比如說這樣就能夠瀏覽它的site-packages。
[root@kevin-test ~]# workon project_kevin               
(project_kevin) [root@kevin-test site-packages]# cdvirtualenv
(project_kevin) [root@kevin-test project_kevin]# ls
bin  include  lib  lib64
 
h) 使用cdsitepackages命令直接進入到 site-packages 目錄中, 和上面的cdvirtualenv 類似
[root@kevin-test ~]# workon project_kevin
(project_kevin) [root@kevin-test ~]# cdsitepackages
(project_kevin) [root@kevin-test site-packages]# ls
easy_install.py  pip                pkg_resources  setuptools-40.6.3.dist-info  wheel-0.32.3.dist-info
easy_install.pyc  pip-18.1.dist-info  setuptools    wheel
 
=============================================
為了方便運維管理, 可以進行一些別名設定, 如下:
[root@kevin-test ~]# vim ~/.bashrc
#virtualenv
alias vte='virtualenv'
alias mkvte='mkvirtualenv'
alias deact='deactivate'
alias rmvte='rmvirtualenv'
alias lsvte='lsvirtualenv'
alias won='workon'
 
使得上面設定生效
[root@kevin-test ~]# source ~/.bashrc
 
使用別名進行操作
[root@kevin-test ~]# lsvte
project_kevin
=============
 
[root@kevin-test ~]# won project_kevin
(project_kevin) [root@kevin-test ~]# deact
 
[root@kevin-test ~]# rmvte project_kevin
Removing project_kevin...
 
[root@kevin-test ~]# lsvte
[root@kevin-test ~]#

virtualenv使用時遇到的一個坑點, 經常排查驗證, 得出結論如下:

1) root使用者和普通使用者都可以建立虛擬環境(比如虛擬環境名稱為venv),venv虛擬環境的相關檔案和資料夾的owner都是該使用者,
    如果是非root的其他使用者啟用該venv虛擬環境的話,會因為檔案許可權的問題導致python庫安裝失敗!!
    所以說: 非root使用者不要去啟用使用其他使用者建立的venv虛擬環境!
 
2) 一旦以使用者A的身份啟用venv虛擬環境後,在虛擬環境中就不能再通過su命令切換其??使用者,否則會自動退出虛擬環境!
    所以說: 在虛擬環境中不要通過su切換使用者!
 
3) 以使用者A的身份啟用某venv虛擬環境後,在虛擬環境中所有通過"sudo + cmd"執行的命令,都等同於在虛擬環境外執行。
    所以說: 在虛擬環境中不要通過sudo執行命令
 
以上提到的3個小問題,在使用virtualenv的時候一定要注意。


IT145.com E-mail:sddin#qq.com