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 修复了问题也只能在新版本中解决,所以若是有跨平台需求还须要先肯定是否正常。