A Better Pip Workflow™python
Python 開發中通常會使用 virtualenv
pip
管理項目運行環境與依賴。在建立一個新項目時先使用 virtualenv
建立一個虛擬運行環境,而後使用 pip
安裝依賴,最後使用 pip freeze > requirements.txt
記錄項目依賴。這個過程當中會遇到一些問題:git
解決上述問題通常的作法是生成多個 requirements.txt
,好比:requirements-dev.txt
、requirements-prod.txt
並記錄好依賴版本信息,或者選擇 Pipenv: Python Dev Workflow for Humans 。github
從名字能夠很直觀的看出 pipenv
= pip
+ virtualenv
。shell
pipenv
在項目開發過程當中使用 pipenv
體驗基本與 pip
一致,並且因爲 pipenv
也會同時管理虛擬環境,體驗上流程更順滑。pipenv
使用 Pipfile
與 Pipfile.lock
來管理依賴信息,Pipfile.lock
會根據安裝的依賴包記錄 hash 校驗值與版本信息。緩存
在新建項目目錄下能夠經過如下方式建立虛擬環境:bash
$ pipenv --python 3.6
複製代碼
$ pipenv --python /path/to/python
複製代碼
$ pipenv install requests --python 3.6
複製代碼
注意:若是沒有使用 --python
參數指定 Python 版本則會使用默認的 Python 版本建立,若是想指定默認 Python 版本能夠經過環境變量 PIPENV_DEFAULT_PYTHON_VERSION
配置,能夠設置爲 Python 版本號:3.6.8
或 Python 解釋器程序路徑。網絡
若是須要虛擬運行環境目錄指定在項目目錄下建立,有兩種方式能夠實現:app
pipenv
前先建立 .venv
目錄$ mkdir .venv && pipenv install requests --python 3.6
複製代碼
PIPENV_VENV_IN_PROJECT
環境變量$ export PIPENV_VENV_IN_PROJECT=1
複製代碼
若是想自定義這個目錄則須要經過環境變量 WORKON_HOME
來配置。工具
對於現有項目,能夠區分爲三種狀況:ui
pipenv
使用 pipenv install -r path/to/requirements.txt --python 3.6
來安裝依賴。
經過 pipenv lock -r > requirements.txt
生成與 pip 相同格式的依賴管理文件。
根據須要可使用 pipenv install
或 pipenv sync
。二者都會建立虛擬環境,使用指定的 PyPI 源按照依賴包,區別是 pipenv install
會根據 Pipfile
中的版本信息安裝依賴包,並從新生成 Pipfile.lock
;而 pipenv sync
會根據 Pipfile.lock
中的版本信息安裝依賴包。
也就是 pipenv install
安裝的依賴包版本可能被更新,具體的機制在依賴包管理中進一步說明。
能夠先激活虛擬環境,再來運行 Python :
$ pipenv shell
複製代碼
或者直接運行:
$ pipenv run python main.py
複製代碼
在項目根目錄下有 .env
環境配置文件時,激活虛擬環境同時會加載 .env
文件中的環境變量配置,若是不想使用這個功能能夠經過配置 PIPENV_DONT_LOAD_ENV
變量來關閉它。
pipenv
安裝包的使用方式與 pip
基本一致,直接在項目目錄下執行 pipenv install request
時 會安裝到虛擬環境目錄下,沒有虛擬環境則會建立後安裝。
沒有指定版本信息時,Pipfile
中不會註明版本,若是在新目錄中使用 pipenv install
直接安裝依賴包的最新版本。
$ pipenv install requests
複製代碼
如下方式會指定爲 1.2
或以上版本,但不會大於等於 2.0
,使用pipenv install
安裝依賴時,若是新版本在 1.2
到 2.0
之間(不包含 2.0
版本)就會更新
$ pipenv install 「requests~=1.2」
複製代碼
更多的版本指定方式以下:
$ pipenv install "requests>=1.4" # 版本號大於或等於 1.4.0
$ pipenv install "requests<=2.13" # 版本號小於或等於 2.13.0
$ pipenv install "requests>2.19" # 版本號大於 2.19.0
複製代碼
若是僅僅在開發 環境下使用這個包,能夠添加 --dev
參數安裝:
$ pipenv install ipython --dev
複製代碼
$ pipenv update --outdated
複製代碼
$ pipenv update
複製代碼
$ pipenv update request
複製代碼
注意:升級依賴包的版本時受到 Pipfile
中版本信息限制,若是想安裝超出限制的版本,則須要執行 pipenv install <pkg>
安裝。
$ pipenv uninstall requests
複製代碼
$ pipenv graph
複製代碼
安裝或卸載依賴包以後,pipenv
都會更新 pipfile
與 pipfile.lock
pip
一般會使用 pip.conf
或者 --index-url
參數來配置 PyPI 鏡像源,pipenv
中有多種配置方式:
PIPENV_PYPI_MIRROR
配置。$ export PIPENV_PYPI_MIRROR=https://mirrors.aliyun.com/pypi/simple/
複製代碼
pipfile
文件配置。經過項目 pipfile
文件中的 [[source]]
節也能夠配置安裝源,而且只對該項目生效。
[[source]]
name = "pypi"
url = "https://mirrors.aliyun.com/pypi/simple/"
verify_ssl = true
...
複製代碼
pyenv
使用Linux 和 macOS 下能夠安裝 pyenv
配合使用,在使用 pipenv
時若是指定的 Python 版本沒有安裝,就會調用 pyenv
進行編譯安裝。
首先請參考 pyenv: Common build problems - Prerequisites 安裝好編譯依賴。
而後根據 Simple Python Version Management: pyenv - Installation 安裝好 pyenv
。
注意:Windows 用戶請手動下載 Python 安裝包安裝,經過 pipenv --python X:\Python\...\python.exe
指定 Python 版本,若是想編譯安裝請自行解決。
pyenv
能夠根據須要配置源碼緩存與編譯臨時文件路徑,解決由於網絡問題沒法下載源碼包,或者 /tmp
分區空間不足形成編譯安裝失敗。
添加緩存目錄,而後將源碼包存放到緩存目錄,而且編譯失敗時不會從新下載源碼包。
$ mkdir -p $(pyenv root)/cache
複製代碼
默認使用系統臨時文件路徑 /tmp
,指定其餘路徑爲臨時文件目錄。
$ mkdir ~/tmp
$ export TMPDIR="$HOME/tmp"
複製代碼
--enable-shared
參數編譯$ env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.6.8
複製代碼
pipenv
爲了保證部署時安裝的依賴版本與發佈一致,不能使用 pipenv install
進行安裝,須要加上 --deploy
參數。
$ pipenv install --deploy
複製代碼
若是不使用虛擬環境,還須要加上 --system
參數
$ sudo pipenv install --deploy --system
複製代碼
pipenv
這裏給一個 Dockerfile 做爲參考。
FROM python:3.6.8
ENV PIP_INDEX_URL https://mirrors.aliyun.com/pypi/simple/
RUN pip3 install pipenv --no-cache-dir
RUN set -ex && mkdir /app WORKDIR /app
COPY Pipfile Pipfile COPY Pipfile.lock Pipfile.lock RUN set -ex && pipenv install --deploy --system
COPY . /app EXPOSE 8888
CMD ["python3", "main.py"] 複製代碼
也能夠先構建一個 Base Image ,而後在構建應用鏡像時使用,假設構建的 Base Image tag 爲 tomczhen/python-pipenv-base:3.6.8
。
FROM python:3.6.8
ENV PIP_INDEX_URL https://mirrors.aliyun.com/pypi/simple/
RUN pip3 install pipenv --no-cache-dir
RUN set -ex && mkdir /app WORKDIR /app
ONBUILD COPY Pipfile Pipfile ONBUILD COPY Pipfile.lock Pipfile.lock ONBUILD RUN set -ex && pipenv install --deploy --system 複製代碼
FROM tomczhen/python-pipenv-base:3.6.8
COPY . /app EXPOSE 8888
CMD ["python3", "main.py"] 複製代碼
pipenv
的缺點固然,pipenv 也有缺點存在。
Lock updating is very slow · Issue #1914 · pypa/pipenv
這是一個代價問題。
因爲須要根據依賴關係以及文件 hash 來生成 Pipfile.lock
,這個問題應該是沒法在短時間內完全解決的,須要在 pipenv
帶來的依賴管理功能與速度上作一個權衡取捨。
目前的辦法是在安裝依賴時使用 pipenv install --skip-lock
來跳過生成/更新 Pipfile.lock
,而後在須要時執行 pipenv lock
來生成/更新 Pipfile.lock
嚴格來講這並不算是 pipenv
的問題。
部分包在跨平臺時的依賴不一樣,好比 PyInstaller 能夠在多個平臺使用,但僅在 Windows 上才依賴 pywin32 包,因爲 Pipfile.lock
是根據安裝的包生成的,在以前的 pipenv
版本中會形成跨平臺時安裝依賴失敗(當前新版本中沒有問題)。
根據 Problem with Pipfile and system specific packages · Issue #1575 · pypa/pipenv 中的討論看,即使 pywin32 修復了問題也只能在新版本中解決,所以若是有跨平臺需求還須要先肯定是否正常。