對於每個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
virtualenvwrapper
是virtualenv
的一個擴充套件包,可以讓你更加方便的使用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
pyenv
是Python
版本管理工具,可以改變全域性的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
下。
總結:利用pyenv
和pyenv-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
專案會自動載入的,要是每次更改了專案程式碼後,容器中的程式碼也變化的話那豈不是容器中的服務也自動載入了?是不是?
幸好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
複製程式碼
最後,如果是生產環境記得把程式碼掛載給去掉,因為線上不需要這樣做,只需要構建一次就行。
參考資料:
- virtualenv-chinese-docs.readthedocs.io/en/latest/
- virtualenvwrapper.readthedocs.io/en/latest/
- github.com/pyenv/pyenv
- TDD開發容器化的Python微服務應用(一)
掃描下面的二維碼(或微信搜尋iEverything
)新增我微信好友(註明python
),然後可以加入到我們的python
討論群裡面共同學習