利用pipenv和pyenv管理多个相互独立的Python虚拟开发环境


Posted in Python onNovember 01, 2020

我们经常会遇到这样的开发需求,比如你手头有多个开发项目,其中项目A要求用python3.7,项目B需要用python3.6,有要求项目A和项目B依赖包相互独立,互不干扰。为了满足这样的开发需求,我们需要在自己的电脑上安装多个Python版本,并且项目之间进行环境隔离。要想安装多个Python版本,可以利用pyenv这个好用的工具,对于建立多个项目之间隔离的开发环境,可以借助于pipenv这个更加好用的包管理工具。

这篇文章将给大家介绍如何利用pyenv和pipenv来管理我们的python开发环境,主要讲两个核心内容:
1.如何在同一台电脑上管理多个版本Python;
2.为每一个项目建立相互隔绝的虚拟环境。

01 — 安装多个Python版本

我们自己开发的多个项目或者从github上clone的项目,可能依赖不同的Python解释器。因此,我们要想运行这些项目,在工作电脑上就要安装不同版本的Python。

pyenv是Python版本管理工具,利用它可以在同一台电脑上安装多个版本的Python,这个过程非常简单。

1.1、安装或升级pyenv

首先安装pyenv,如果你是Mac电脑,那么推荐使用Homebrew来安装。

$ brew update && brew install pyenv

要想升级pyenv,则可以执行:

$ brew update && brew upgrade pyenv

如果不是Mac电脑,那么就用github方式来安装:

$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.bash_profile
$ exec "$SHELL"

这种安装方式的详细说明,还是建议大家参考官方文档:https://github.com/pyenv/pyenv#basic-github-checkout。

对于github安装的pyenv,可以按下面方式进行升级:

$ cd $(pyenv root)
$ git fetch
$ git tag
v1.2.18
$ git checkout v1.2.18

pyenv安装完成后,需要将$(pyenv root)/shims添加到PATH变量前面,这一步非常关键。

$ echo 'export PATH="$(pyenv root)/shims:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile

1.2、用pyenv安装Python

安装完pyenv,可以安装Python啦,一共需要两步。

$ pyenv install 3.7.7
$ pyenv rehash

执行命令pyenv versions查看安装结果。

$ pyenv versions
 system
* 3.7.7 (set by /Users/chunming.liu/.pyenv/version)

可以看到,已经成功安装了Python 3.7.7,安装的位置在/Users/chunming.liu/.pyenv。

1.3、切换Python版本

可以通过pyenv global或者pyenv local切换Python版本。pyenv global属于全局切换,切换完成后,在系统中任何地方执行python,你会发现都是同样的Python版本。

$ pyenv global 3.7.7
$ pyenv versions
 system
* 3.7.7 (set by /Users/chunming.liu/.pyenv/version)

可以看到,3.7.7前面有一个星号,说明成功切换到了3.7.7版本,可以执行一下python来验证一下:

$ python
Python 3.7.7 (default, Apr 12 2020, 12:31:11)
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

pyenv local属于局部切换,只能修改当前目录下的Python版本,出了当前目录则失效。

接下来,开始为每个项目建立独立的开发环境。

02 — 用Pipenv创建虚拟环境

Pipenv是Python官方推荐的包管理工具。它综合了 virtualenv , pip 和 pyenv 三者的功能。你可以使用pipenv这一个工具来安装、卸载、跟踪和记录依赖性,并创建、使用和组织你的虚拟环境。

2.1、安装和升级pipenv

如果你是Mac电脑,那么推荐使用Homebrew来安装和升级pipenv:

$ brew update && brew install pipenv
$ brew update && brew upgrade pipenv

也可以通过pip来安装和升级pipenv:

$ pip install pipenv
$ pip install --upgrade pipenv

2.2、为项目建立虚拟环境

进入到项目目录中,通过下面的指令为项目创建虚拟环境。

$ mkdir pipenv_demo
$ cd pipenv_demo
$ pipenv --python 3.7.7
Creating a virtualenv for this project…
Pipfile: /Users/chunming.liu/work/pipenv_demo/Pipfile
Using /Users/chunming.liu/.pyenv/versions/3.7.7/bin/python3 (3.7.7) to create virtualenv…
⠙ Creating virtual environment...Using base prefix '/Users/chunming.liu/.pyenv/versions/3.7.7'
New python executable in /Users/chunming.liu/.local/share/virtualenvs/pipenv_demo-RYMSREda/bin/python3
Also creating executable in /Users/chunming.liu/.local/share/virtualenvs/pipenv_demo-RYMSREda/bin/python
Installing setuptools, pip, wheel...
done.
Running virtualenv with interpreter /Users/chunming.liu/.pyenv/versions/3.7.7/bin/python3
​
✔ Successfully created virtual environment!
Virtualenv location: /Users/chunming.liu/.local/share/virtualenvs/pipenv_demo-RYMSREda

上面的操作,给pipenv_demo这个项目初始化了一个Python 3.7.7的虚拟环境,并在项目录下生成一个项目依赖包文件Pipefile。如果系统中没有3.7.7版本的Python,pipenv会调用pyenv来安装对应的Python的版本。

默认地,虚拟环境会创建在~/.local/share/virtualenvs目录里面。我们也可以通过pipenv --venv查看项目的虚拟环境目录。可以通过 pipenv --rm 删除虚拟环境。

如果想更改虚拟环境的目录,可以在 .bashrc 或 .bash_profile 中,设置环境变量WORKON_HOME,指定虚拟环境的目录所在位置,比如想将虚拟环境放到~/.venvs目录,则可以执行下面的命令。

$ echo 'export WORKON_HOME=~/.venvs' >> ~/.bash_profile
$ source ~/.bash_profile

如果希望在项目目录下创建虚拟环境目录(.venv),需要在 .bashrc 或 .bash_profile 中配置环境变量PIPENV_VENV_IN_PROJECT:

$ echo 'export PIPENV_VENV_IN_PROJECT=1' >> ~/.bash_profile
$ source ~/.bash_profile

03 — 用Pipenv管理依赖包

pipenv使用 Pipfile 和 Pipfile.lock 来管理依赖包,并且在使用pipenv添加或删除包时,自动维护 Pipfile 文件,同时生成 Pipfile.lock 来锁定安装包的版本和依赖信息。相比pip需要手动维护requirements.txt 中的安装包和版本,具有很大的进步。

3.1 安装依赖包

为项目安装依赖包到虚拟环境中,使每个项目拥有相互独立的依赖包,是非常不错的Python的开发实践。安装依赖包到虚拟环境中的方法:

$ pipenv install pytest
Installing pytest…
Adding pytest to Pipfile's [packages]…
✔ Installation Succeeded
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
✔ Success!
Updated Pipfile.lock (1c4d3d)!
Installing dependencies from Pipfile.lock (1c4d3d)…
 ?  ???????????????????????????????? 11/11 — 00:00:16
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

执行完上面的命令后,检查一下是否安装成功:

$ pipenv graph
pytest==5.4.1
 - attrs [required: >=17.4.0, installed: 19.3.0]
 - importlib-metadata [required: >=0.12, installed: 1.6.0]
  - zipp [required: >=0.5, installed: 3.1.0]
 - more-itertools [required: >=4.0.0, installed: 8.2.0]
 - packaging [required: Any, installed: 20.3]
  - pyparsing [required: >=2.0.2, installed: 2.4.7]
  - six [required: Any, installed: 1.14.0]
 - pluggy [required: >=0.12,<1.0, installed: 0.13.1]
  - importlib-metadata [required: >=0.12, installed: 1.6.0]
   - zipp [required: >=0.5, installed: 3.1.0]
 - py [required: >=1.5.0, installed: 1.8.1]
 - wcwidth [required: Any, installed: 0.1.9]

可看到已经安装了pytest,还列出了pytest的依赖包。

观察项目的根目录下,又多了一个Pipfile.lock文件。这两个文件记录了此项目的依赖包,这两个文件的区别是 Pipfile中安装的包不包含包的具体版本号,而Pipfile.lock是包含包的具体的版本号的。如果不想产生Pipfile.lock文件,在安装依赖包的时候,加上?skip-lock选项即可。

打开依赖包文件Pipefile,可以看到python_version = “3.7”,说明这个项目是基于Python 3.7版本的。package部分列出来了项目的依赖包是bpytest = “*”,星号代表最新版本。

而Pipfile.lock是包含安装的依赖包具体的版本号,可以看到本次安装的pytest是5.4.1版本,并且它的依赖包的版本也列出来了。

$ cat Pipfile.lock
{
  "_meta": {
    "hash": {
      "sha256": "828b8ad012f4c8773e6e61e3ac2be0ffcd7540fd7ed175a8355676c8e31c4d3d"
    },
    "pipfile-spec": 6,
    "requires": {
      "python_version": "3.7"
    },
    "sources": [
      {
        "name": "pypi",
        "url": "https://pypi.org/simple",
        "verify_ssl": true
      }
    ]
  },
  "default": {
    "attrs": {
      "hashes": [
        "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c",
        "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"
      ],
      "version": "==19.3.0"
    },
    "importlib-metadata": {
      "hashes": [
        "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f",
        "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"
      ],
      "markers": "python_version < '3.8'",
      "version": "==1.6.0"
    },
    "more-itertools": {
      "hashes": [
        "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c",
        "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"
      ],
      "version": "==8.2.0"
    },
    "packaging": {
      "hashes": [
        "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3",
        "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"
      ],
      "version": "==20.3"
    },
    "pluggy": {
      "hashes": [
        "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
        "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
      ],
      "version": "==0.13.1"
    },
    "py": {
      "hashes": [
        "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa",
        "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"
      ],
      "version": "==1.8.1"
    },
    "pyparsing": {
      "hashes": [
        "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
        "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
      ],
      "version": "==2.4.7"
    },
    "pytest": {
      "hashes": [
        "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172",
        "sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970"
      ],
      "index": "pypi",
      "version": "==5.4.1"
    },
    "six": {
      "hashes": [
        "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
        "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
      ],
      "version": "==1.14.0"
    },
    "wcwidth": {
      "hashes": [
        "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1",
        "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"
      ],
      "version": "==0.1.9"
    },
    "zipp": {
      "hashes": [
        "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b",
        "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"
      ],
      "version": "==3.1.0"
    }
  },
  "develop": {}
}

3.2 提高依赖包安装速度

在使用pipenv的时候,常常会安装过程比较慢,通过加上 -v 参数,可以看到安装过程中的步骤信息,卡在了下载那里,这时应该可以意识到是因为网络的原因,pipenv创建的 Pipfile 中默认的Pypi源是python官方的 https://pypi.python.org/simple。我们国内用户访问下载的时候会很慢。

如果想通过Pypi的国内镜像安装依赖包,可以在安装软件包时,指定?pypi-mirror,比如通过清华大学镜像安装flask软件包:

$ pipenv install --pypi-mirror https://pypi.tuna.tsinghua.edu.cn/simple flask

为了避免每次都要指定?pypi-mirror,我一般会在创建好Pipfile以后,将文件中 source 块下的 url 字段,设置为国内的 pypi 源,我推荐的是清华的Pypi源或者阿里源,具体设置如下:

[[source]]
 url = "https://pypi.tuna.tsinghua.edu.cn/simple"
 verify_ssl = true
 name = "pypi"

3.3 删除依赖包

如果是要删除虚拟环境中的第三方包,执行

$ pipenv uninstall pytest

3.4 安装项目所有的依赖包

用git管理项目时候,要把Pipfile和Pipfile.lock加入版本跟踪。这样clone了这个项目的同学,只需要执行

$ pipenv install

就可以安装所有的Pipfile中 [packages]部分列出来的包了,并且自动为项目在自己电脑上创建了虚拟环境。

3.5 安装pipefile.lock中的依赖包

上面的方法都是安装Pipfile中列出来的第三方包的最新版本,如果是想安装Pipfile.lock中固定版本的第三方依赖包,需要执行:

$ pipenv install --ignore-pipfile

3.6 安装requirements.txt里面的依赖包

如果项目之前使用requirements.txt来管理依赖的,那么使用pipenv安装所有依赖可以采用类似pip的方法:

$ pipenv install -r requirements.txt

04 — 使用虚拟环境进行开发

虚拟环境创建好了之后,就可以在里面进行开发了。

如果在命令行下开发,则在项目目录下执行pipenv shell,就进入到了虚拟环境中,在这个环境中,已经包含安装过的所有依赖包了,接下来就可以利用这些依赖包进行开发工作了。

$ pipenv shell
Launching subshell in virtual environment…
bash-3.2$ . /Users/chunming.liu/.local/share/virtualenvs/pipenv_demo-RYMSREda/bin/activate
(pipenv_demo) bash-3.2$ python
Python 3.7.7 (default, Apr 12 2020, 12:31:11)
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pytest
>>>

如果是用Pycharm进行开发,就更简单了,直接用Pycharm打开项目即可。可以从Pycharm中的左侧导航栏里面看到External Libraries显示的是虚拟环境中的Python解释器了。

在虚拟环境中执行开发好的程序,有两种方式,一种是前面提到的先执行pipenv shell进入到虚拟环境后,再执行python程序;另一种方式,则是执行pyenv run,比如在虚拟环境中执行基于pytest框架编写的测试用例,只需要执行下面的命令即可:

$ pipenv run py.test

04 — 总结

本文给大家介绍了如何使用pyenv安装多个版本Python,如何在不同的Python版本间切换。还介绍了一种Python官方推荐使用的包管理工具pipenv,它结合pyenv和pip和virtualenv的优点于一身,可以帮我们管理项目的虚拟环境、管理项目的依赖包。

在这里插入图片描述

非常建议大家尝试一下pyenv和pipenv。在实践中,推荐大家将Pipfile和Pipfile.lock加入版本跟踪,不要将虚拟环境.venv加入版本管理,因为这个包比较大,而且可以pipenv install方式重建。为每一个项目项目建立独立的虚拟环境,为每一个项目使用Pipfile管理依赖是一个非常好的实践。

参考资料

https://github.com/pyenv/pyenv

https://github.com/pypa/pipenv

https://packaging.python.org/tutorials/managing-dependencies/#installing-pipenv

https://hackersandslackers.com/pipenv-python-environment-management/

到此这篇关于利用pipenv和pyenv管理多个相互独立的Python虚拟开发环境的文章就介绍到这了,更多相关pipenv和pyenv管理多Python虚拟环境内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python实现嵌套列表及字典并按某一元素去重复功能示例
Nov 30 Python
python去掉空白行的多种实现代码
Mar 19 Python
无法使用pip命令安装python第三方库的原因及解决方法
Jun 12 Python
Python全排列操作实例分析
Jul 24 Python
python的xpath获取div标签内html内容,实现innerhtml功能的方法
Jan 02 Python
使用python批量化音乐文件格式转换的实例
Jan 09 Python
python 切换root 执行命令的方法
Jan 19 Python
python全栈要学什么 python全栈学习路线
Jun 28 Python
使用Nibabel库对nii格式图像的读写操作
Jul 01 Python
利用Python实现朋友圈中的九宫格图片效果
Sep 03 Python
Python远程linux执行命令实现
Nov 11 Python
python 利用PyAutoGUI快速构建自动化操作脚本
May 31 Python
Python经纬度坐标转换为距离及角度的实现
Nov 01 #Python
详解Anaconda安装tensorflow报错问题解决方法
Nov 01 #Python
python Cartopy的基础使用详解
Nov 01 #Python
Python中使用aiohttp模拟服务器出现错误问题及解决方法
Oct 31 #Python
关于python中导入文件到list的问题
Oct 31 #Python
python批量检查两个对应的txt文件的行数是否一致的实例代码
Oct 31 #Python
Python在线和离线安装第三方库的方法
Oct 31 #Python
You might like
php中字符串和正则表达式详解
2014/10/23 PHP
如何判断图片地址是否失效
2007/02/02 Javascript
jQuery aminate方法定位到页面具体位置
2013/12/26 Javascript
jQuery 插件开发指南
2014/11/14 Javascript
谷歌浏览器调试JavaScript小技巧
2014/12/29 Javascript
javascript 操作符(~、&amp;、|、^、)使用案例
2014/12/31 Javascript
jQuery实现单击和鼠标感应事件
2015/02/01 Javascript
JavaScript制作windows经典扫雷小游戏
2015/03/31 Javascript
详解vue-router 2.0 常用基础知识点之router.push()
2017/05/10 Javascript
详解如何让Express支持async/await
2017/10/09 Javascript
vue + element-ui的分页问题实现
2018/12/17 Javascript
基于js实现抽红包并分配代码实例
2019/09/19 Javascript
js实现简单的点名器随机色实例代码
2020/09/20 Javascript
Ant-design-vue Table组件customRow属性的使用说明
2020/10/28 Javascript
[03:18]DOTA2亚洲邀请赛小组赛第一日 RECAP赛事回顾
2015/01/30 DOTA
[37:22]DOTA2上海特级锦标赛D组资格赛#2 Liquid VS VP第一局
2016/02/28 DOTA
Python语言描述机器学习之Logistic回归算法
2017/12/21 Python
Python 获得命令行参数的方法(推荐)
2018/01/24 Python
django2用iframe标签完成网页内嵌播放b站视频功能
2018/06/20 Python
python判断字符串或者集合是否为空的实例
2019/01/23 Python
python根据txt文本批量创建文件夹
2020/12/08 Python
python 修改本地网络配置的方法
2019/08/14 Python
python如何使用jt400.jar包代码实例
2019/12/20 Python
pandas 中对特征进行硬编码和onehot编码的实现
2019/12/20 Python
Python openpyxl模块原理及用法解析
2020/01/19 Python
python matplotlib imshow热图坐标替换/映射实例
2020/03/14 Python
澳大利亚便宜隐形眼镜购买网站:QUICKLENS Australia
2018/10/06 全球购物
软件毕业生个人鉴定
2014/03/03 职场文书
乡党委干部党的群众路线教育实践活动个人对照检查材料思想汇报
2014/10/01 职场文书
扬州个园导游词
2015/02/06 职场文书
2015年宣传工作总结
2015/04/08 职场文书
停电通知范文
2015/04/16 职场文书
新生儿未入户证明
2015/06/23 职场文书
品牌形象定位,全面分析
2019/07/23 职场文书
JS Object构造函数之Object.freeze
2021/04/28 Javascript
MyBatis配置文件解析与MyBatis实例演示
2022/04/07 Java/Android