在开发 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
- 不方便管理--激活,消活
deactivate
,环境切换等 - 没法重用--存放在指定项目目录下
而 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 都是使用的星号*
,未指定特定的包版本。因此在更新/同步等操做时会将全部未指定版本 (使用星号*
)的第三方库给更新了。这里强烈建议生产环境的第三方库都指定版本。bashPipfile.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
容器当前的环境以下图所示: 使用
workon proEnv
进入虚拟环境 proEnv 后,各参数以下图所示:
对比 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 看不见什么软件包的缘由,也是环境隔离的最大秘密。
参考文献
若是该文章对您产生了帮助,或者您对技术文章感兴趣,能够关注微信公众号: 技术茶话会, 可以第一时间收到相关的技术文章,谢谢!
本篇文章由一文多发平台ArtiPub自动发布