利用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制作爬虫并将抓取结果保存到excel中
Apr 06 Python
python中map()函数的使用方法示例
Sep 29 Python
详解python中的 is 操作符
Dec 26 Python
Python3中bytes类型转换为str类型
Sep 27 Python
python自动化测试无法启动谷歌浏览器问题
Oct 10 Python
PyCharm 2019.3发布增加了新功能一览
Dec 08 Python
使用python去除图片白色像素的实例
Dec 12 Python
python中的线程threading.Thread()使用详解
Dec 17 Python
Python加速程序运行的方法
Jul 29 Python
python实现单机五子棋
Aug 28 Python
详解Python+OpenCV绘制灰度直方图
Mar 22 Python
如何Python使用re模块实现okenizer
Apr 30 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 友好URL的实现(吐血推荐)
2008/10/04 PHP
PHP中的日期加减方法示例
2014/08/21 PHP
Laravel 5框架学习之Eloquent (laravel 的ORM)
2015/04/08 PHP
Zend Framework上传文件重命名的实现方法
2016/11/25 PHP
javascript 子窗体父窗体相互传值方法
2010/05/31 Javascript
简单实例处理url特殊符号&amp;处理(2种方法)
2013/04/02 Javascript
利用JS进行图片的切换即特效展示图片
2013/12/03 Javascript
如何屏蔽防止别的网站嵌入框架代码
2015/08/24 Javascript
js 右侧浮动层效果实现代码(跟随滚动)
2015/11/22 Javascript
AngularJS基础 ng-keydown 指令简单示例
2016/08/02 Javascript
Ionic2系列之使用DeepLinker实现指定页面URL
2016/11/21 Javascript
JS中如何实现Laravel的route函数详解
2017/02/12 Javascript
原生JS实现《别踩白块》游戏(兼容IE)
2017/02/20 Javascript
JavaScript实现一个空中避难的小游戏
2017/06/06 Javascript
Angularjs在360兼容模式下取数据缓存问题的解决办法
2017/06/22 Javascript
搭建element-ui的Vue前端工程操作实例
2018/02/23 Javascript
微信小程序—setTimeOut定时器的问题及解决
2019/07/26 Javascript
在 Vue 中编写 SVG 图标组件的方法
2020/02/24 Javascript
详解Python列表赋值复制深拷贝及5种浅拷贝
2019/05/15 Python
python 实现创建文件夹和创建日志文件的方法
2019/07/07 Python
解决Python3用PIL的ImageFont输出中文乱码的问题
2019/08/22 Python
Pycharm自动添加文件头注释和函数注释参数的方法
2020/10/23 Python
python中doctest库实例用法
2020/12/31 Python
预订全球最佳旅行体验:Viator
2018/03/30 全球购物
德国滑雪和户外用品网上商店:XSPO
2019/10/30 全球购物
营销与策划个人求职信
2013/09/22 职场文书
自考毕业自我鉴定范文
2013/10/27 职场文书
毕业生就业自荐书
2013/12/15 职场文书
大学军训感想
2014/02/12 职场文书
环境工程专业自荐信
2014/03/03 职场文书
2014年专项整治工作总结
2014/11/17 职场文书
赔偿协议书
2015/01/27 职场文书
小班下学期个人总结
2015/02/12 职场文书
反腐倡廉观后感
2015/06/08 职场文书
2016教师政治学习心得体会
2016/01/23 职场文书
MySQL Server层四个日志的实现
2022/03/31 MySQL