Python 虛擬環境全知道

陽明先生發表於2018-01-09

對於每個python專案依賴的庫版本都有可能不一樣,如果將依賴包都安裝到公共環境的話顯然是沒法進行區分的,甚至是不同的專案使用的python版本都不盡相同,有的用python2.7,有的用python3.6,所以對於python專案的環境進行隔離管理就成為一個必然的需求了。

需求

  • 不同專案間能區分依賴包版本
  • 不同專案間能區分python版本
  • 方便自由切換

解決方案

  • 解決依賴包問題:virtualenv
  • 解決python版本問題:pyenv
  • 終極(也許吧)解決方案:docker

virtualenv

執行pip install virtualenv即可安裝virtualenv,當然了還可以用easy_install安裝,即使是沒有安裝任何Python包管理器(比如pip),也可以直接獲取virtualenv.py並執行python virtualenv.py,效果也是一樣的,當然我還是強烈推薦你安裝包管理工具:pip,他一定能為你帶來很多便利的(新版本的virtualenv也包含了pip管理工具)。

$ pip install virtualenv
Collecting virtualenv
  Using cached virtualenv-15.1.0-py2.py3-none-any.whl
Installing collected packages: virtualenv
Successfully installed virtualenv-15.1.0
複製程式碼

安裝完成後,就可以直接建立一個虛擬環境了(virtualenv 環境名稱):

$ virtualenv env4test
複製程式碼

建立完成後,用下面的命令即可啟用當前虛擬環境:

$ source env4test/bin/activate
(env4test)$
複製程式碼

現在就可以隨意的安裝你的依賴包了,現在安裝的包只會對當前環境env4test有效,比如安裝django2.0

(env4test)$ pip install django
複製程式碼

要退出當前虛擬環境也是非常簡單的,如下:

$ deactivate
複製程式碼

現在我們用pip list命令可以發現已經沒有django的身影了。

virtualenv還有很多高階的用法,可以前往該文件檢視

virtualenvwrapper

virtualenvwrappervirtualenv的一個擴充套件包,可以讓你更加方便的使用virtualenv,優點:

  • 將所有虛擬環境整合在一個目錄下
  • 管理(新增,刪除,複製)虛擬環境
  • 方便切換虛擬環境

安裝也很方便,用包管理工具即可:

$ pip install virtualenvwrapper
複製程式碼

安裝完成以後還需要小小的配置一下才可以使用,首先我們找到virtualenvwrapper.sh的文章,通常會是:/usr/local/bin/virtualenvwrapper.sh

$ sudo find / -name virtualenvwrapper.sh
Password:
/usr/local/bin/virtualenvwrapper.sh
複製程式碼

然後我們可以在.zshrc(取決於你用的終端,我用的zsh)新增一行命令:

source /usr/local/bin/virtualenvwrapper.sh
複製程式碼

然後讓我們的配置生效:

$ source ~/.zshrc
複製程式碼

現在我們就可以使用virtualenvwrapper的基本命令了:

  • 建立基本環境:mkvirtualenv [環境名]
  • 刪除環境:rmvirtualenv [環境名]
  • 啟用環境:workon [環境名]
  • 退出環境:deactivate
  • 列出所有環境:workon或者lsvirtualenv -b

參考文件:virtualenvwrapper.readthedocs.io/en/latest/

pyenv

pyenvPython版本管理工具,可以改變全域性的Python版本,安裝多個版本的Pytho,設定目錄級別的Python版本,還能建立和管理虛擬環境。所有的設定都是使用者級別的操作,不需要sudo命令。 pyenv通過系統修改環境變數來實現Python不同版本的切換。而virtualenv 通過將Python包安裝到一個目錄來作為Python 包虛擬環境,通過切換目錄來實現不同包環境間的切換。

如果你使用的MAC系統,推薦使用homebrew來安裝:

$ brew update
$ brew install pyenv
複製程式碼

如果你使用的是其他系統,也不擔心,pyenv官方提供了一鍵安裝的方式:

$ curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
複製程式碼

安裝完成以後,可以新增幾條命令到.zshrc(同樣的也可能是.bashrc,根據自己使用的終端進行配置)中開啟自動補全功能:

export PATH=$HOME/.pyenv/bin:$PATH
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
複製程式碼

然後同樣啟用上面的配置:

$ source ~/.zshrc
複製程式碼

現在我們就可以使用pyenv了:

  • 檢視本機安裝 Python 版本:
$ pyenv versions
* system (set by /Users/ych/.pyenv/version)
  3.6.4
  3.6.4/envs/ops3.6.4
  3.6.4/envs/talk3.6.4
  ops3.6.4
  talk3.6.4
複製程式碼

星號表示當前正在使用的Python版本。

  • 檢視所有可安裝的Python版本:
$ pyenv install -l
複製程式碼
  • 安裝與解除安裝:
$ pyenv install 2.7.3   # 安裝python
$ pyenv uninstall 2.7.3 # 解除安裝python
複製程式碼
  • 版本切換:
$ pyenv global 2.7.3
$ pyenv local 2.7.3
複製程式碼

global用於設定全域性的Python版本,通過將版本號寫入~/.pyenv/version檔案的方式。local用於設定本地版本,通過將版本號寫入當前目錄下的.python-version檔案的方式。通過這種方式設定的Python版本優先順序比global高。

  • python優先順序:shell > local > global pyenv會從當前目錄開始向上逐級查詢.python-version檔案,直到根目錄為止。若找不到,就用global版本。
$ pyenv shell 2.7.3 # 設定面向 shell 的 Python 版本,通過設定當前 shell 的 PYENV_VERSION 環境變數的方式。這個版本的優先順序比 local 和 global 都要高。
$ pyenv shell --unset  # –unset 引數用於取消當前 shell 設定的版本。
複製程式碼

pyenv-virtualenv

自動安裝pyenv後,它會自動安裝部分外掛,通過pyenv-virtualenv外掛可以很好的和virtualenv進行結合:

$ ls -la ~/.pyenv/plugins
total 8
drwxr-xr-x   9 ych  staff  288 12 26 16:27 .
drwxr-xr-x  23 ych  staff  736 12 26 17:44 ..
-rw-r--r--   1 ych  staff   52 12 26 16:26 .gitignore
drwxr-xr-x  11 ych  staff  352 12 26 16:27 pyenv-doctor
drwxr-xr-x  12 ych  staff  384 12 26 16:27 pyenv-installer
drwxr-xr-x   7 ych  staff  224 12 26 16:27 pyenv-update
drwxr-xr-x  13 ych  staff  416 12 26 16:27 pyenv-virtualenv
drwxr-xr-x   8 ych  staff  256 12 26 16:27 pyenv-which-ext
drwxr-xr-x   8 ych  staff  256 12 26 16:26 python-build
複製程式碼

基本使用命令:

  • 列出當前虛擬環境:pyenv virtualenvs
  • 啟用虛擬環境:pyenv activate 環境名稱
  • 退出虛擬環境:pyenv deactivate
  • 刪除虛擬環境:pyenv uninstall 環境名稱或者rm -rf ~/.pyenv/versions/環境名稱
  • 建立虛擬環境:pyenv virtualenv 3.6.4 env3.6.4

若不指定python 版本,會預設使用當前環境python 版本。如果指定Python 版本,則一定要是已經安裝過的版本,否則會出錯。環境的真實目錄位於~/.pyenv/versions下。

總結:利用pyenvpyenv-virtualenv外掛就能夠簡單方便的將python版本和依賴包進行環境隔離了,在實際開發過程中比較推薦這種方式。

參考文件:github.com/pyenv/pyenv

Docker

有沒有一種方式能夠不按照這些工具來進行環境隔離的呢?當然有,那就是大名鼎鼎的Docker。如果你的服務都是容器化的話,應該對Docker不陌生,將當前專案跑在一個隔離的容器中,對系統中的其他服務或者專案是沒有任何影響的,不用擔心會汙染環境,唯一不友好的地方是專案中的程式碼改變後需要重新構建映象。

比如現在有一個django的專案,專案結構如下:

$ testpyenv  tree
.
├── manage.py
└── testpyenv
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
複製程式碼

在專案根目錄下面新建檔案requirements.txt

Django==2.0
複製程式碼

然後我們在根目錄下面建立一個Dockerfile檔案:

FROM python:3.6.4

# 設定工作目錄
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# 新增依賴(利用Docker 的快取)
ADD ./requirements.txt /usr/src/app/requirements.txt

# 安裝依賴
RUN pip install -r requirements.txt

# 新增應用
ADD . /usr/src/app

# 執行服務
CMD python manage.py runserver 0.0.0.0:8000
複製程式碼

因為django2.0只支援python3以上了,所以我們這裡基礎映象使用python:3.6.4,然後是新增應用程式碼,安裝依賴,執行服務等。然後我們構建一個映象:

$ docker build -t cnych/testpyenv:v0.1.1 .
複製程式碼

構建完成以後,在我們專案根目錄中新建一個start.sh的指令碼來啟動容器:

docker run -d -p 8000:8000 --name testpyenv cnych/testpyenv:v0.1.1
複製程式碼

將本地的8000埠和容器的8000進行對映,執行我們的啟動指令碼:

$ source start.sh
複製程式碼

啟動完成後,我們就可以在本地通過http://127.0.0.1:8000進行訪問了。

django-index
但是如果只這樣配置的話,的確能夠解決我們的環境隔離問題,但是現在有一個最大的一個問題是,每次程式碼更改過後都需要重新構建映象才能生效,這對於開發階段是非常不友好的,有什麼解決方案呢?你是否還記得當你更改了程式碼後django專案會自動載入的,要是每次更改了專案程式碼後,容器中的程式碼也變化的話那豈不是容器中的服務也自動載入了?是不是?

幸好Docker為我們提供了volume掛載的概念,我們只需要將我們的程式碼掛載到容器中的工作目錄就行了,現在來更改start.sh指令碼:

work_path=$(pwd)
docker run -d -p 8000:8000 --name testpyenv -v ${work_path}:/usr/src/app cnych/testpyenv:v0.1.1
複製程式碼

然後啟用啟動指令碼,隨意更改一次程式碼,看看是否能夠及時生效,怎樣檢視呢?檢視日誌就行了:

$ docker logs -f testpyenv
複製程式碼

最後,如果是生產環境記得把程式碼掛載給去掉,因為線上不需要這樣做,只需要構建一次就行。

參考資料:

點選檢視原文連結

掃描下面的二維碼(或微信搜尋iEverything)新增我微信好友(註明python),然後可以加入到我們的python討論群裡面共同學習

qrcode

相關文章