Python多环境管理神器(pipenv)

pipenv

参考官网://pipenv.pypa.io/

pipenv 是一款比较新的包管理工具,其借鉴了 javascript 的 npm 和 PHP 的 composer 等理念,通过一个依赖描述文件 Pipfile 来安装和管理依赖,以达到协同开发的目的。如果你熟悉 npm 或者 composer 的话,那 pipenv 正合你胃口。pipenv 其实整合了 pip 和 virtualenv 等库,在其上推出了更便捷的使用方式。

1、安装pipenv

直接使用pip命令安装

pip3 install pipenv 

设置命令行的自动补全功能

如果使用的bash shell,请将以下代码添加到 .bashrc 或 .bash_profile 文件内:

eval "$(pipenv --completion)" 

参考://blog.csdn.net/swinfans/article/details/89305301

命令详解:

$ pipenv
Usage: pipenv [OPTIONS] COMMAND [ARGS]...

Options:
  --where             输出项目根目录相关信息
  --venv              输出virtualenv相关信息
  --py                输出Python解释器相关信息
  --envs              输出环境变量选项
  --rm                删除virtualenv
  --bare              最小化输出
  --completion        命令自动补全
  --man               显示man页面
  --three / --two     在创建virtualenv时使用Python3或Python2
  --python TEXT       指定创建virtualenv时使用的具体的Python版本
  --site-packages     为virtualenv启用site-packages [env变量:PIPENV_SITE_PACKAGES]
  --clear             清除缓存(pipenv,pip和pip-tools)[env变量:PIPENV_CLEAR]
  --pypi-mirror TEXT  指定一个PyPI镜像
  --version           显示版本信息并退出
  -h, --help          显示帮助信息并退出


使用示例:
   创建一个项目,并明确指定使用Python3.7:
   $ pipenv --python 3.7

   删除项目的virtualenv (inferred from current directory):
   $ pipenv --rm

   为项目安装所有依赖项 (including dev):
   $ pipenv install --dev

   创建包含pre-releases的lockfile文件:
   $ pipenv lock --pre

   将已安装的依赖项显示为图表:
   $ pipenv graph

   检查已安装的依赖项是否存在安全漏洞:
   $ pipenv check

   安装一个本地的setup.py到你的虚拟环境或Pipfile:
   $ pipenv install -e .

   使用原生的pip命令:
   $ pipenv run pip freeze

Commands:
  check      根据 Pipfile 中提供的PEP 508标记检查安全漏洞
  clean      卸载所有 Pipfile.lock 未指定的包
  graph      显示当前安装的依赖项的关系图信息
  install    如果未指定要安装的包,则会安装 Pipfile 中的所有包,否则,只安装指定的包
  lock       生成 Pipfile.lock 文件
  open       在编辑器中查看给定的模块
  run        运行virtualenv中已安装的命令
  shell      在virtualenv内启动一个shell
  sync       安装 Pipfile.lock 中指定的所有的包
  uninstall  卸载一个指定的包并将其从 Pipfile 中移除
  update     先运行lock命令,在运行sync命令

2、pipenv虚拟环境管理

2.1、虚拟环境创建与激活

创建虚拟环境

# 进入项目目录:
[[email protected] data]# mkdir myproj10
[[email protected] data]# cd myproj10/
[[email protected] myproj10]# ls
[[email protected] myproj10]# pipenv install

上面的命令会自动在~/.local/share/virtualenvs/目录下创建虚拟环境目录,

名字为一个当前目录名加一串随机字符串的虚拟环境目录。这里是myproj10-740tHe3W

创建过程如下图:

clipboard

下面多了两个文件,为Pipfile和Pipfile.lock,用于存放依赖包名的文件。

类似php里的composer.json和composer.lock。

[[email protected] myproj10]# ls
Pipfile  Pipfile.lock

查看虚拟环境

[[email protected] myproj10]# pipenv --venv
/root/.virtualenvs/myproj10-740tHe3W

我们的虚拟环境目录在/root/.virtualenvs/下面,是因为我们之前设置过环境变量

export WORKON_HOME=$HOME/.virtualenvs 

激活虚拟环境:

cd /data/myproj10
pipenv shell

激活后如下图:

clipboard

注意:上面激活虚拟环境的时候,出现了这么一个告警:

Warning: Your Pipfile requires python_version 2.7, but you are using 3.9.9 (/root/./m/bin/python).

原因:这是因为创建虚拟环境的时候,没有指定python解释器,Pipfile就使用系统默认的python解释器了,就是2.7.5,但是pipenv却是使用系统最新的解释器3.9.

解决办法:

办法一:手动修改Pipfile

手动修改Pipfile文件里的python_version

注意:Pipfile.lock里的也要修改

vim Pipfile

[[source]]
url = "//pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]

[dev-packages]

[requires]
python_version = "3.9"

办法二:删除虚拟环境,重新创建虚拟环境

删除虚拟环境后,再次安装会覆盖之前的Pipfile,使用新环境。如果不删除,无法覆盖。

# pipenv --rm删除当前虚拟环境,注意Pipfile不会被删掉
[[email protected] myproj10]# pipenv --rm
# 使用pipenv重新安装,指定解释器版本为3.X
[[email protected] myproj10]# pipenv install --three
# 此时再次查看Pipfile版本就和环境一致了。
[[email protected] myproj10]# cat Pipfile

如下图:

clipboard

退出虚拟环境:exit

((myproj10) ) [[email protected] myproj10]# exit
exit
[[email protected] myproj10]#

刚创建好虚拟环境的时候,会自动进入虚拟环境,并且此时是没有前缀显示,此时需要用exit退出。

当后面用pipenv shell激活的时候,会显示前缀,此时可以用exit退出,也可以使用deactivate退出。

clipboard

删除虚拟环境

[[email protected] myproj10]# pipenv --rm 
Removing virtualenv (/root/.virtualenvs/myproj10-740tHe3W)...

2.2、创建虚拟环境的多种方式

pipenv创建虚拟环境有多种方式,这里总结一下:

方式一:指定解释器创建虚拟环境

# 创建虚拟环境
pipenv --three
# 或者
pipenv --python 3.9

这种方式是指定python解释器,并创建虚拟环境。

它会在当前目录生成Pipfile,不会生成Pipfile.lock

这种方式创建虚拟环境后,会自动进入虚拟环境,但是进入后也不会显示前缀

clipboard

方式二:安装所有依赖时创建虚拟环境

# 创建虚拟环境
pipenv install

这种方式是在安装依赖包的同时创建虚拟环境。

因为pipenv install,就是根据Pipfile来安装所有依赖,类似npm install

如果当前目录没有Pipfile,它就会自动创建Pipfile并创建虚拟环境。

因为这种方式它已经在安装所有依赖了,所以不仅会创建Pipfile,也会创建Pipfile.lock文件。

同时,它创建虚拟环境后,也会自动进入环境,但是也不会显示前缀。

如下图:

clipboard

方式三:激活时创建虚拟环境

# 激活,如果环境不存在,则创建虚拟环境并激活
pipenv shell

这个命令主要用于激活环境,但是如果环境不存在,则会先创建虚拟环境,并同时激活虚拟环境。

这种方式因为使用了pipenv shell激活了,所以创建虚拟环境后,也会自动进入虚拟环境,并激活。

会显示虚拟环境前缀。

如下图:

clipboard

2.3、修改虚拟环境目录位置

有三种方法:

方法一:

# 方法一:
# 设置这个环境变量,pipenv会在当前目录下创建.venv的目录,以后都会把模块装到这个.venv下。
export PIPENV_VENV_IN_PROJECT=1

方法二:

# 自己在项目目录下手动创建.venv的目录,然后运行 pipenv run 或者 pipenv shell pipenv都会在.venv下创建虚拟环境。
mkdir .venv
pipenv shell

方法三:

# 设置WORKON_HOME到其他的地方 (如果当前目录下已经有.venv,此项设置失效)。
export WORKON_HOME=$HOME/.virtualenvs

注意:

小技巧: 如果子级目录的父级目录已经创建过虚拟环境, 则子级目录无法创建虚拟目录(子级目录无法生成Pipfile, 子级默认会使用父级的虚拟环境), 如果确实需要在子级目录创建独立的虚拟环境,可以运行pipenv –where 获取父级虚拟环境的名字, 根据虚拟环境的前半部分名字, 确定父级目录的位置, 然后删除父级目录下的Pipfile, Pipfile.lock, 运行exit退出父级虚拟环境,然后回到子目录,运行pipenv –three创建子目录的虚拟环境即可

2.4、相关定位操作

定位项目目录:

[[email protected] aaa]# pipenv --where
/data/myproj10

定位虚拟环境目录,即virtualenv目录

[[email protected] aaa]# pipenv --venv
/root/.virtualenvs/myproj10-740tHe3W

定位Python解释器:

[[email protected] aaa]# pipenv --py
/root/.virtualenvs/myproj10-740tHe3W/bin/python

如下图:

clipboard

3、pipenv包管理

安装依赖包:

安装相关依赖包,并加入到Pipfile

pipenv install flask

它会在当前环境安装flask依赖包,并记录flask包名以及版本信息,记录到Pipfile里。

如果安装的时候,没有指定包名,默认是最新的,会记录为“*”

注意:Pipfile只会记录你install里指定的包,但是这个flask包本身所依赖的包不会记录,

但是所有的依赖详情都会记录到Pipfile.lock中。

clipboard

Pipfile.lock类似如下:

clipboard

查看目前安装的库及其依赖关系

pipenv graph

如下图:这是所有的完整依赖关系,这些会记录在Pipfile.lock中。

clipboard

Pipfile会记录当前虚拟环境安装的所有依赖包及其对应的版本,当我们需要迁移项目,部署新项目,或者有新人接手时,就可以直接拿到这个Pipfile和Pipfile.lock文件,直接pipenv install即可,它就会按照Pipfile里的包,把所有的依赖文件都安装上,是不是很方便。

安装所有依赖包:

# 根据Pipfile的记录,安装所有依赖包
pipenv install

指定安装包版本:

你可以使用 语义化(//semver.org/)的版本控制方案 指定包的版本。例如 major.minor.micro 。

例如,你可以使用如下的命令安装 requests:

pipenv install requests~=1.2   # 相当于 requests~=1.2.0

Pipenv 将安装 1.2 版本和任何 minor 版本的更新,但不会安装 2.0 版本。

上面的命令将会自动更新 Pipfile 文件以体现这个特殊的需求。

通常,Pipenv使用与pip相同的参数格式。但是,请注意,根据PEP 440,您不能使用包含连字符或加号的版本号。

要指定包含或者排除具体的版本,您可以使用如下命令:

pipenv install "requests>=1.4"   # 只安装等于或者大于 1.4.0 的版本
pipenv install "requests<=2.13"  # 只安装小于或者等于 2.13.0 的版本
pipenv install "requests>2.19"   # 安装 2.19.1 版本但是不安装 2.19.0 版本

注意:强烈建议使用双引号包裹包名和版本号以避免unix操作系统中的输入和输出重定向问题。

请优先使用 ~= 标识符而不是 == 标识符,因为后者会阻止 pipenv 更新包:

pipenv install "requests~=2.2"  # 锁定包的主版本(这相当于使用==2.*)

要避免安装某个特定的版本,可以使用 != 标识符。

要深入解释有效标识符和更复杂的用例,请查看 PEP-440 的相关部分。

//www.python.org/dev/peps/pep-0440/#version-specifiers%3E

卸载依赖包:

卸载指定包:

pipenv uninstall flask

卸载包后,相关包和依赖详情会从Pipfile和Pipfile.lock中移除。

clipboard

卸载当前环境所有包:

# 从虚拟环境中移除所有已安装的包,但 Pipfile.lock 文件不受影响
pipenv uninstall --all

卸载开发包:

# 从虚拟环境中卸载所有开发包,并从 Pipfile 文件中移除这些包
pipenv uninstall –all-dev

更新依赖包:

查看所有需要更新的包:

pipenv update --outdated

如下图:

clipboard

更新指定包:

pipenv update <包名>

更新所有包:

pipenv update

检查安全漏洞:

pipenv check  # 检查安全漏洞

它可能会检查出很多错误,其实如果不影响你使用,你可以直接忽略掉。强迫症患者也可以一个一个问题去解决。

比如如下问题:

clipboard

修改pipenv的镜像源

可以修改当前目录下Pipfile文件,将[source]下的url属性改成国内的源即可:

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

3、环境部署

使用pipenv进行多环境部署

dev与正式环境区分安装。

当你想要一个包只在开发环境使用,等生产部署的时候,不需要该安装包,你可以这样指定环境安装。

# 把django安装在开发环境
pipenv install django --dev

安装如下图

clipboard

安装完成后,查看Pipfile文件:

会发现,pipenv已经将安装包区分开来了。

[dev-packages] 里记录的–dev开发环境安装的包

[package] 里记录的是没有加环境参数,默认就是正式环境的包。

clipboard

那么等到你真正迁移到生产环境部署的时候,就只需要这么做:

pipenv install

这样默认是只安装[package] 里的安装包的,会自动过滤掉[dev-packages] 里的包。

让生产环境变得更加纯净,避免有多余的包。

如下:这是直接pipenv install的,里面是没有django包的

clipboard

如果你要迁移到开发环境,只需要这么做:

pipenv install --dev

它就会把[dev-packages] 里的包也一起安装上了。

如下:

这是使用了–dev参数的,看到已经把djiango安装上了。

clipboard

4、Pipfile.lock文件

Pipfile.lock 利用了pip中一些新的安全改进。默认情况下,Pipfile.lock 包含每个下载的包的 sha256 哈希值。这可以使pip能够保证从不信任的PyPI源安装包时或者在不稳定的网络环境下安装包时都能保证包的正确性与完整性。我们强烈建议通过将项目从开发环境提升到生产环境来进行部署。您可以使用 pipenv lock 编译开发环境上的依赖项,并将编译后的 Pipfile.lock 文件部署到您所有的生产环境,以便进行可重现的构建。

(使用Pipfile.lock可以锁定之前的安装包,确保迁移重新部署后,能够重现跟之前一样的环境。)

Pipfile和Pipfile.lock不一致

因为使用pipenv install的时候,加上–ignore-lock参数,可以忽略 Pipfile.lock 文件而直接安装 Pipfile 中的包。此外,不会更新 Pipfile.lock 文件。

当pipenv install安装一些比较大的包,比如TensorFlow等科学包,在安装完包,正在解析包依赖的时候,可能会花费很长时间,可能就会ctrl+C停止掉了,此时包已经安装完成,Pipfile已经写入完成,但是没有解析完依赖,所以Pipfile.lock没有写入完成。

这两种情况都会导致Pipfile和Pipfile.lock不一致的情况,会对应不上。

此时,可以使用Pipenv lock重新生成Pipfile.lock文件。

pipenv lock

如果通过 pipenv 命令安装和卸载 package,安装或卸载完成后还会更新 Pipfile.lock 文件,有时候会卡在这个步骤。通常可以 ctrl+c 强制推出,删除 Pipfile.lock, 然后

# 重新生成Pipfile.lock文件
pipenv lock

默认情况下,使用pipenv install,它会重新解析Pipfile里安装包的依赖性,并将依赖关系更新到Pipfile.lock中。如果你不想要重新解析Pipfile里安装包,只想安装Pipfile.lock文件中现存的依赖包,可以精确的指定只使用Pipfile.lock文件。

pipenv sync

可以使用 sync 命令精确安装 Pipfile.lock 文件中指定的包:

pipenv sync 

注意:pipenv install –ignore-pipfile 和 pipenv sync 命令很相似,但是pipenv sync 命令永远不会尝试重新锁定依赖项,因为它被认为是一个原子操作。默认情况下,除非使用了 –deploy 标志,否则 pipenv install 会尝试重新锁定依赖项。

pipenv install --deploy

可以使用 –deploy 标志强制Pipfile.lock 文件是最新的。

上述命令将在Pipfile.lock 文件不是最新的时候导致构建失败,而不是生成一个新的。

5、兼容requirements.txt

之前我们的pip工具可以从requierments.txt文件中导入依赖包。

在pipenv,用下面的命令就可以将Pipfile和Pipfile.lock文件里面的包导出为requirements.txt文件。

# 将Pipfile里的全部包导出到requirements.txt
pipenv lock -r > requirements.txt

内容如下:

clipboard

可以选择只导出开发环境的包:

# 只导出开发环境的包
pipenv lock -r --dev-only > requirements.txt

如下图:

clipboard

导出开发环境+ 默认的环境的包:

# dev环境和default环境的包都会导出
pipenv lock -r --dev > requirements.txt

如下图:

clipboard

也可以使用底层pip的命令导出:

pipenv run pip freeze > requirements.txt

如下图:

clipboard

导入requirements.txt

导出为requirements.txt后,可以通过pip导入,也可以通过pipenv导入。

# 通过pip导入
pip install -r requirements.txt
# 通过pipenv导入
pipenv install -r requirements.txt

6、虚拟环境中运行命令:

启动shell运行

正常来说,如果想要让命令运行在虚拟环境,需要启动一个虚拟环境的shell,否则命令还是在系统环境下运行的,如下:

pipenv shell

如下图:

clipboard

使用run运行:

如果不想启动shell,而是直接在虚拟环境中执行命令,可以使用run:

# pipenv run <命令>
pipenv run python --version

如下图:

clipboard

部署项目的时候,你也可以不进入虚拟环境的方式运行项目:

pipenv run python xxx.py

7、环境变量:(.env)

自动加载.env文件 (利器)

.env文件可以设置一些环境变量,在程序开发的时候模拟环境变量。

如果项目目录下包含一个 .env 文件,它会被 pipenv shell 和 pipenv run 命令自动加载:

# 如下,设置一个变量HELLO,以及配置文件路径的变量
[[email protected] myproj10]# cat .env 
HELLO=WORLD
CONFIG_PATH=${HOME}/.config/foo


# 测试环境变量
# 使用pipenv run的时候,会自动加载该环境变量。
[[email protected] myproj10]# pipenv run python
Loading .env environment variables...
Python 3.9.9 (main, Dec 31 2021, 15:34:46) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ['HELLO']
'WORLD'
>>> os.environ['CONFIG_PATH']
'/root/.config/foo'
>>> 

这类似于php的lavel框架的.env文件。

这对于将生产凭证排除在代码库之外非常有用。我们不建议将 .env 文件提交到源代码控制中!

如果你的 .env 文件位于不同的路径下或者有其他名称,你可以设置一个PIPENV_DOTENV_LOCATION 环境变量:

PIPENV_DOTENV_LOCATION=/path/to/.env pipenv shell

要禁止pipenv加载 .env 文件,可以设置 PIPENV_DONT_LOAD_ENV 环境变量:

PIPENV_DONT_LOAD_ENV=1 pipenv shell

Pipfile引用环境变量:

在Pipfile中也可以引用环境变量的值,格式为${MY_ENVAR}或$MY_ENVAR,在Windows系统中还支持%MY_ENVAR%。

[[source]]
url = "//${PYPI_USERNAME}:${PYPI_PASSWORD}@my_private_repo.example.com/simple"
verify_ssl = true
name = "pypi"

[packages]
flask = "*"
jieba = "*"

[dev-packages]
django = "*"

[requires]
python_version = "3.9"

这里的变量为:${PYPI_USERNAME}:${PYPI_PASSWORD}

使用前提是,系统中要已经设置了相关的变量。

当然你可以结合.env文件,将相关变量设置在.env里。

从setup.py安装依赖包

很多依赖库都包含setup.py文件,里面也包含了对应包的子依赖信息,这个文件跟Pipfile.lock有点相似,pipenv也提供了堆setup.py的支持。

pipenv也可以从setup.py安装:

pipenv install -e .

更多pipenv的用法,请参考官网://pipenv.pypa.io/en/latest/

8、优缺点分析:

1、pipenv集成了pip,virtualenv两者的功能,且完善了两者的一些缺陷。

2、支持Python2 和 Python3,在各个平台的命令都是一样的。

3、类似npm,容易迁移,便于项目内部协同工作

4、各个地方使用了哈希校验,无论安装还是卸载包都十分安全,且会自动公开安全漏洞。

5、通过加载.env文件简化开发工作流程。

6、Bug 很多,确实比较年轻,安装的流程有些让人困惑,不像 pip 这么直接好理解

参考引用:

//blog.csdn.net/swinfans/article/details/89305301

//pipenv.pypa.io/en/latest/

Tags: