Python項目的虛擬環境

在開發 Python 項目時,首先要肯定使用的 Python 版本,目前默認是 3.7(Python 2.7 已經在 2020 年中止支持了,可是須要維護的項目中確定有很多基於 Python 2.x 版本的),其次會根據項目的需求來選擇特定版本的第三方庫(通常都會選擇最新版本的,除非不一樣庫之間有衝突)。可是使用 pip 安裝第三方庫時默認都會安裝到 Python3 的 site-packages 目錄中,一旦不一樣項目中的第三方庫版本出現衝突時,就比較難處理了。因此咱們須要對不一樣的項目開闢獨立乾淨的空間進行開發部署,此時就須要 Python 的虛擬環境了。本文將介紹 virtualenv 和 pipenv 兩種途徑構建虛擬環境,可是 pipenv 的方式更值得推廣html

virtualenv

virtualenv 是一個建立隔絕的 Python 環境的工具。它會建立一個包含全部必要的可執行文件的文件夾,用來使用 Python 工程所須要的包。換句話說,咱們能夠用 virtualenv 給各個項目建立各自的 Python 環境,各個的環境之間安裝的包相互獨立,互不影響。經過激活 avtive 相應的 Python 環境來使用相應的 Python 環境。這裏爲了方便管理不一樣的 Python 環境,咱們使用 virtualenvwrapper 來對 Python 虛擬環境進行管理。python

安裝和配置

virtualenv 和 virtualenvwrapper 的安裝很簡單,一條命令便可:git

pip install virtualenv  # 安裝virtualenv
pip install virtualenvwrapper # 安裝virtualenvwrapper

virtualenv 是不須要配置的,它的使用直接是在項目文件夾裏執行命令 virtualenv proEnv ,就會在當前項目目錄下生成proEnv的目錄,目錄下會包含 bin,include,lib,local 這四個文件夾和一個 pip-selfcheck.json 文件。當該虛擬環境被激活後 source proEnv/bin/activate ,全部執行的 pip 安裝程序都會安裝在當前虛擬環境文件夾 proEnv 中。不過這樣就致使下面的問題:github

  1. 不方便管理--激活,消活 deactivate ,環境切換等
  2. 沒法重用--存放在指定項目目錄下

而 virtualenvwrapper 能完美解決這些問題。docker

virtualenvwrapper 的配置以下:shell

# 1.在~/.bashrc文件結尾添加下面(根據特定環境而定)
source /usr/local/bin/virtualenvwrapper.sh

# 2. 從新加載配置
source $HOME/.bashrc

經常使用命令

# 建立環境    
mkvirtualenv proEnv [-p python3.7]  # 在$HOME/.virtualenvs/目錄下建立項目python環境

# 列舉全部環境
lsvirtualenv

# 切換環境
workon proEnv

# 退出環境
deactivate

# 刪除環境
revirtualenv proEnv

pipenv

pipenv 是 Pipfile 主要倡導者、requests 做者 Kenneth Reitz 寫的一個命令行工具,主要包含了 Pipfile、pip、click、requests 和 virtualenv,可以有效管理 Python 多個環境,各類第三方包及模塊。json

pipenv 所解決的問題:flask

  • 不一樣項目依賴不一樣的第三方庫、包版本問題( virtualenv 也能夠解決)
  • 同一個項目不一樣環境使用不用的第三方庫問題(好比 autopep8 , pylint , pep8 等只有開發環境須要)

pipenv的特性:安全

  • pipenv 集成了 pip,virtualenv 二者的功能,且完善了二者的一些缺陷。
  • 過去用 virtualenv 管理 requirements.txt 文件可能會有問題,Pipenv 使用 Pipfile 和 Pipfile.lock,後者存放包的依賴關係,查看依賴關係是十分方便。
  • 各個地方使用了哈希校驗,不管安裝仍是卸載包都十分安全,且會自動公開安全漏洞。
  • 經過加載 .env 文件簡化開發工做流程。
  • 支持 Python2 和 Python3,在各個平臺的命令都是同樣的。

TIPS:
《Flask Web開發實戰》的做者在該書中使用了 Pipenv 做爲包管理工具,可是在 2019 年 8 月又發表了博文不要用 Pipenv,其核心的槽點是 pipenv 在更新第三方依賴庫時會更新全部依賴的包,其緣由是對應的 packages 都是使用的星號*,未指定特定的包版本。因此在更新/同步等操做時會將全部未指定版本 (使用星號*)的第三方庫給更新了。這裏強烈建議生產環境的第三方庫都指定版本bash

Pipfile.lock 文件更像是當前環境的一個快照,並非指以前安裝的第三方依賴庫的版本就是肯定的,除非你在 Pipfile 中限定好版本。

安裝

pipenv 的安裝很簡單,一條命令便可:

# 安裝pipenv包來管理依賴庫
python3 -m pip install pipenv
# 設置環境變量,在項目目錄建立虛擬環境.venv
export PIPENV_VENV_IN_PROJECT=1

常見的 Pipfile 配置以下所示:

[[source]]
name = "aliyun"
url = "https://mirrors.aliyun.com/pypi/simple"
verify_ssl = true

[dev-packages]
autopep8 = "*"
pylint = "*"
pep8 = "*"


[packages]
flask = "==1.1.2"

[requires]
python_version = "3.7"

常見命令

  • 建立虛擬環境
# 開發環境安裝 Pipfile 中第三方依賴
pipenv intall -d
# 生成環境安裝 Pipfile 中第三方依賴
pipenv install
# 安裝requirements.txt中的依賴庫(項目遷移)
pipenv install -r requirements.txt
# 將pipenv的依賴庫生成requirements.txt(項目遷移)
pipenv run pip freeze > requirements.txt
  • 使用環境
# 直接在虛擬環境中運行
pipenv run python test.py
# 激活虛擬環境,再運行腳本
pipenv shell && python test.py && exit
  • 安裝卸載第三方依賴
# 安裝第三方依賴庫,並加到 Pipfile 的開發環境中
pipenv install -d pylint
# 安裝指定版本的第三方依賴庫,並加到 Pipfile 的生成環境中
pipenv install Flask==1.1.2
# 卸載第三方依賴庫,並更新 Pipfile
pipenv uninstall Flask
  • 查看依賴包
# 查看當前環境依賴的包
pipenv graph

虛擬環境的原理

pipenv 是基於 Pipfile,結合 pip 和 virtualenv來幫助開發者進行依賴管理,因此要想搞明白虛擬環境的原理其實只要把 virtualenv 的原理搞明白便可。 這裏咱們使用 pytyhon:3.7-stretch 鏡像進行實驗(不使用alpine鏡像是由於它默認的 shell 是 ash,而不是 bash)。

現象分析

虛擬環境的特色有二:

  • Python版本固定。即便系統的Python升級了,虛擬環境中的仍然不受影響,保留開發狀態。
  • 全部Python軟件包,都只在這個環境生效。一旦退出,則回到用戶/系統的默認環境中。

因此猜想 virtualenv 是經過改變 shell 的 PATH 來實現指定的 Python 版本,而對應的軟件包是各自維護在各自的虛擬環境目錄中的。

驗證手段

  • echo $PATH Python 命令的查找路徑
  • pip list 查看當前環境的依賴庫
  • python -m site 打印當前 Python 環境和 site-packages 相關調試信息

驗證

# 啓動容器
docker run -it --rm python:3.7-stretch bash
# 安裝virtualenv和virtualenvwrapper
pip install virtualenv virtualenvwrapper
# 在 $HOME/.bashrc 文件結尾添加 source /usr/local/bin/virtualenvwrapper.sh
echo "source /usr/local/bin/virtualenvwrapper.sh" >> $HOME/.bashrc
# 從新加載配置
source $HOME/.bashrc
# 建立虛擬環境proEnv
mkvirtualenv proEnv

容器當前的環境以下圖所示: virtualenv_before 使用 workon proEnv 進入虛擬環境 proEnv 後,各參數以下圖所示: virtualenv_after

對比 PATH 的變化,發現 virtualenv 將虛擬環境的 bin 目錄置於 PATH 的最前方,因此當在終端執行 python 時,執行的是 /root/.virtualenvs/proEnv/bin/python, 而不是 /usr/local/bin/python。這就是爲何 virtualenv 沒有影響本地的 Python 環境。

對比 python -m site 的結果,發現虛擬環境的 sys.path 中第三方依賴庫的目錄由 /usr/local/lib/python3.7/site-packages 換成了 /root/.virtualenvs/proEnv/lib/python3.7/site-packages。這就是爲何 pip list 看不見什麼軟件包的緣由,也是環境隔離的最大祕密。

參考文獻

  1. Pipenv中文文檔
  2. python最佳實踐指南
  3. Python開發還在用virtualenv?不如瞭解下pipenv
  4. 不要用 Pipenv

若是該文章對您產生了幫助,或者您對技術文章感興趣,能夠關注微信公衆號: 技術茶話會, 可以第一時間收到相關的技術文章,謝謝!

技術茶話會


本篇文章由一文多發平臺ArtiPub自動發佈
相關文章
相關標籤/搜索