关于我

一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。

Github:https://github.com/hylinux1024

微信公众号:终身开发者(angrycode)

Python拥有大量的第三方库,引用这些库也非常方便,通过pip install就可以将这些第三方库安装到本地Python库文件目录中,然后就可以import到项目中,极大地提升了开发者的编码效率。

但这也带来了一个问题:当A项目和B项目同时引用Lib库,而A项目需要Lib版本是1.0,B项目需要Lib的版本是2.0。这样在使用pip install命令将Lib直接安装到本地全局环境中就会发生冲突,有可能会导致AB的运行环境无法同时得到满足而运行失败。

于是虚拟环境(virtualenv)就出现了。它的核心思想就是为每个项目提供独立的运行环境,这样不同的项目依赖库就不会冲突。

0x00 使用venv+pip

1、创建venv

安装虚拟环境也非常简单,可以使用venv模块,例如在项目目录中使用Python3创建一个虚拟环境

 ➜ python3 -m venv venv

于是在项目目录中就多了一个venv的文件目录。这个目录就是该项目的虚拟环境。

要使用虚拟环境就必须激活

 ➜ source venv/bin/activate

然后在命令行中就会出现

(venv) ➜

说明虚拟环境已经激活。

要取消虚拟环境,使用

(venv) ➜ deactivate

2、使用pip install/uninstall

激活虚拟环境后就可以使用pip命令安装项目的依赖库。例如

(venv) ➜ pip install requests

pip会将requests安装到venv/lib/python3.7/site-packages目录中。

要卸载依赖库

(venv) ➜ pip uninstall requests

3、pip list

要查看venv中安装了哪些依赖库

(venv) ➜ pip list
Package Version
-------------- --------
beautifulsoup4 4.7.1
certifi 2019.3.9
requests 2.21.0

4、pip freeze

使用pip freeze可以将依赖库列表保存到一个requirements.txt文件,可以让其他项目的协作者可以快速地建立项目的运行环境。

(venv) ➜ pip freeze > requirements.txt

于是要安装项目依赖

(venv) ➜ pip install -r requirements.txt

这样就可以建立一个统一的运行环境了。

5、venv+pip方案存在的问题

到目前为止一切都运行良好,这应该是不错的解决方案了吧。实际上这种方案我一直都在使用,目前也是,也并没有遇到什么问题。

直到有一天有人说使用venv+pip也不能保证我的运行环境的一致性和可靠性

他的理由也很简单,项目的库环境是依赖requirements.txt,而requirements.txt中库有没有指定版本号,这样在使用pip install -r requirements.txt的时候也会导致安装不确定的版本。

例如

beautifulsoup4
certifi
requests

当然可以为每个库指定确切的版号来解决,于是

beautifulsoup4 4.7.1
certifi 2019.3.9
requests 2.21.0

这样做可以解决上面的问题,但是如果某个第三方库修补了一个漏洞,要使用pip install --upgrade更新这些依赖库的话,就不是那么容易了。

还有一个问题requirements.txt中的依赖库也有可能会出现版本号冲突。 情况是这样:

ALib -> sublib_1.0
BLib -> sublib_2.1

ALibBLib同时依赖于sublib,但它们依赖的版本不一样,最终在使用pip install -r requirements.txt也可能会因为依赖库中的子依赖库版本不兼容而导致项目运行失败。

于是就出现了pipenv

0x01 pipenv

说实话在这之前我一直都是使用venv+pip,当看到上面的问题之后,我觉得有必要了解一下pipenv

1、安装pipenv

➜ pip install pipenv

一旦安装完成就会引用两个文件,PipfilePipfile.lock。前者是用于取代requirements.txt文件的,后者则是用于保证依赖库的确定性和一致性。

实际上,pipenv命令底层也是封装了pipvenv的操作,并提供了一套简单的交互命令。

创建虚拟环境

要在项目目录下(如pipenvdemo)使用

➜ pipenv shell

当出现类似以下信息时说明虚拟环境创建并激活成功,当然还可以使用--two--three参数指定使用Python2还是Python3来创建,也可以使用确定的Python版本号如--python3.7

➜ pipenv shell --three

➜ pipenv shell --python3.7

由于我电脑本地Python环境是3.7,所以这里直接默认它会指向本地默认版本

Creating a virtualenv for this project…
Pipfile: /Users/mac/PycharmProjects/pipenvdemo/Pipfile
Using /usr/local/opt/python/bin/python3.7 (3.7.3) to create virtualenv…
⠋ Creating virtual environment...Already using interpreter /usr/local/opt/python/bin/python3.7
Using base prefix '/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7'
New python executable in /Users/mac/.local/share/virtualenvs/pipenvdemo-fHPp2Wq9/bin/python3.7
Also creating executable in /Users/mac/.local/share/virtualenvs/pipenvdemo-fHPp2Wq9/bin/python
Installing setuptools, pip, wheel...
done. ✔ Successfully created virtual environment!
Virtualenv location: /Users/mac/.local/share/virtualenvs/pipenvdemo-fHPp2Wq9
Creating a Pipfile for this project…
Launching subshell in virtual environment…
. /Users/mac/.local/share/virtualenvs/pipenvdemo-fHPp2Wq9/bin/activate

同时在项目目录下(如pipenvdemo)生成一个Pipfile文件。类似的,命令行也会出现以下样式

(pipenvdemo) ➜ pipenvdemo

其中Pipfile的内容为

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true [dev-packages] [packages] [requires]
python_version = "3.7"

2、pipenv install

当要安装第三方库当时候就直接使用pipenv install命令,以下指定flask版本号进行安装。

➜ pipenv install flask==1.0.1

也可以不指定版本号

➜ pipenv install flask

终端会出现类似以下信息

Installing flask==1.0.1…
Adding flask to Pipfile's [packages]…
✔ Installation Succeeded
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
⠙ Locking...

还可以使用--dev参数用于安装开发环境依赖的库

➜ pipenv install pytest --dev

在项目目录又生成了另一文件Pipfile.lock,并且Pipfile文件也会更新

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true [dev-packages]
pytest = "*" [packages]
flask = "==1.0.1" [requires]
python_version = "3.7"

看到在[packages]标签下列出了依赖库flask和版本号,上面还有一个[dev-packages]是用于标示开发版本依赖库,这样可以用于区分生产环境和开发环境。只有在命令中使用了--dev参数才会安装[dev-packages]下列出的依赖库。

Pipfile.lock文件的内容要丰富一些,主要是包含了依赖库(包括子依赖库)的版本号以及文件hash的信息,从而可以保证依赖库是确定的。

{
"_meta": {
"hash": {
"sha256": "3bba1f1c4de8dd6f8d132dda17cd3c720372a1eed94b9523b9c23013e951c8ae"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.7"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"click": {
"hashes": [
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
],
"version": "==7.0"
},
"flask": {
"hashes": [
"sha256:cfc15b45622f9cfee6b5803723070fd0f489b3bd662179195e702cb95fd924c8",
"sha256:dbe2a9f539f4d0fe26fa44c08d6e556e2a4a4dd3a3fb0550f39954cf57571363"
],
"index": "pypi",
"version": "==1.0.1"
},
"itsdangerous": {
"hashes": [
"sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
"sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
],
"version": "==1.1.0"
},
"jinja2": {
"hashes": [
"sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
"sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
],
"version": "==2.10.1"
},
"markupsafe": {
"hashes": [
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
],
"version": "==1.1.1"
},
"werkzeug": {
"hashes": [
"sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c",
"sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6"
],
"version": "==0.15.4"
}
},
"develop": {}
}

3、pipenv lock

假设我们要把项目发布到生产环境了,这时就要使用pipenv lock命令

➜ pipenv lock

终端会出现类似如下信息

Locking [dev-packages] dependencies…
✔ Success!
Locking [packages] dependencies…

这个命令会创建或更新Pipfile.lock文件,需要注意的是我们不应该手动修改此文件。

然后就可以在生产环境中使用以下命令恢复环境

➜ pipenv install --ignore-pipfile

指定--ignore-pipfile参数的意思是,只要恢复Pipfile.lock的列表的依赖库和子依赖库。如果要恢复开发环境中的依赖库,即安装[dev-packages]下面的依赖库,可以使用

➜ pipenv install --dev

以上就是pipenv的简单用法。

4、pipenv graph

现在再来看看前面提到的问题

ALib -> sublib_1.0
BLib -> sublib_2.1

AB模块都依赖同一个库,但依赖库的版本号不一样。这时使用pipenv install就出现类似以下信息

Warning: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.
You can use $ pipenv install --skip-lock to bypass this mechanism, then run $ pipenv graph to inspect the situation.
Could not find a version that matches sublib=1.0,sublib=2.1

可以使用

➜ pipenv graph

查看当前项目依赖库及其子依赖库信息,以树层级方式进行展示

Flask==1.0.1
- click [required: >=5.1, installed: 7.0]
- itsdangerous [required: >=0.24, installed: 1.1.0]
- Jinja2 [required: >=2.10, installed: 2.10.1]
- MarkupSafe [required: >=0.23, installed: 1.1.1]
- Werkzeug [required: >=0.14, installed: 0.15.4]
pytest==4.6.2
- atomicwrites [required: >=1.0, installed: 1.3.0]
- attrs [required: >=17.4.0, installed: 19.1.0]
- importlib-metadata [required: >=0.12, installed: 0.17]
- zipp [required: >=0.5, installed: 0.5.1]
- more-itertools [required: >=4.0.0, installed: 7.0.0]
- packaging [required: Any, installed: 19.0]
- pyparsing [required: >=2.0.2, installed: 2.4.0]
- six [required: Any, installed: 1.12.0]
- pluggy [required: >=0.12,<1.0, installed: 0.12.0]
- importlib-metadata [required: >=0.12, installed: 0.17]
- zipp [required: >=0.5, installed: 0.5.1]
- py [required: >=1.5.0, installed: 1.8.0]
- six [required: >=1.10.0, installed: 1.12.0]
- wcwidth [required: Any, installed: 0.1.7]

本例中我们安装了flaskpytestpipenv graph命令展示了它们各自需要的依赖。还可以加上--reverse参数

➜ pipenv graph --reverse

使用这个参数可以很方便的分析出冲突的库。

atomicwrites==1.3.0
- pytest==4.6.2 [requires: atomicwrites>=1.0]
attrs==19.1.0
- pytest==4.6.2 [requires: attrs>=17.4.0]
click==7.0
- Flask==1.0.1 [requires: click>=5.1]
itsdangerous==1.1.0
- Flask==1.0.1 [requires: itsdangerous>=0.24]
MarkupSafe==1.1.1
- Jinja2==2.10.1 [requires: MarkupSafe>=0.23]
- Flask==1.0.1 [requires: Jinja2>=2.10]
more-itertools==7.0.0
- pytest==4.6.2 [requires: more-itertools>=4.0.0]
pip==19.1.1
py==1.8.0
- pytest==4.6.2 [requires: py>=1.5.0]
pyparsing==2.4.0
- packaging==19.0 [requires: pyparsing>=2.0.2]
- pytest==4.6.2 [requires: packaging]
setuptools==41.0.1
six==1.12.0
- packaging==19.0 [requires: six]
- pytest==4.6.2 [requires: packaging]
- pytest==4.6.2 [requires: six>=1.10.0]
wcwidth==0.1.7
- pytest==4.6.2 [requires: wcwidth]
Werkzeug==0.15.4
- Flask==1.0.1 [requires: Werkzeug>=0.14]
wheel==0.33.4
zipp==0.5.1
- importlib-metadata==0.17 [requires: zipp>=0.5]
- pluggy==0.12.0 [requires: importlib-metadata>=0.12]
- pytest==4.6.2 [requires: pluggy>=0.12,<1.0]
- pytest==4.6.2 [requires: importlib-metadata>=0.12]

5、其它命令

删除一个依赖包

➜ pipenv uninstall numpy

删除所有依赖库

➜ pipenv uninstall --all

➜ pipenv uninstall --all-dev

--all-dev是指定删除所有开发环境的依赖。

查看venv目录路径

➜ pipenv --venv

/Users/mac/.local/share/virtualenvs/pipenvdemo-fHPp2Wq9

查看当前项目路径

➜ pipenv --where

/Users/mac/PycharmProjects/pipenvdemo

0x02 总结一下

从目前使用pip+venv的包管理工具遇到的问题出发,提到这种方式遇到的问题是依赖库以及它们的子依赖库又可能会出现版本冲突以及管理的问题。于是有人提出新的包管理工具pipenv。它有两个核心文件PipfilePipfile.lock文件,前者用于指定当前项目中的直接依赖库信息,而后者则指定了依赖的依赖的库信息,通过依赖的hash值以及版本号来确定依赖库的一致性。

0x03 参考引用

关于Python虚拟环境与包管理你应该知道的事的更多相关文章

  1. Python虚拟环境和包管理工具Pipenv的使用详解--看完这一篇就够了

    前言 Python虚拟环境是一个虚拟化,从电脑独立开辟出来的环境.在这个虚拟环境中,我们可以pip安装各个项目不同的依赖包,从全局中隔离出来,利于管理. 传统的Python虚拟环境有virtualen ...

  2. Pipenv——最好用的python虚拟环境和包管理工具

    pipenv 是Kenneth Reitz大神的作品,能够有效管理Python多个环境,各种包.过去我们一般用virtualenv搭建虚拟环境,管理python版本,但是跨平台的使用不太一致,且有时候 ...

  3. Python黑帽编程1.3 Python运行时与包管理工具

    Python黑帽编程1.3  Python运行时与包管理工具 0.1  本系列教程说明 本系列教程,采用的大纲母本为<Understanding Network Hacks Attack and ...

  4. python 工具链 包管理工具 pip

    Installation mac下可以采用 brew,easy_install(python自带)等方式安装. centos下可以采用yum,easy_install等方式安装. 但是上面两种方式在系 ...

  5. Python第一天:你必须要知道的Python擅长领域以及各种重点学习框架(包含Python在世界上的应用)

    目录 Python5大擅长领域 WEB开发 网络编程 科学运算 GUI图形开发 运维自动化 Python在世界上的知名应用 国外 谷歌 CIA NASA YouTube Dropbox Instagr ...

  6. python 工具链 虚拟环境和包管理工具 pipenv

    Pipenv is a tool that aims to bring the best of all packaging worlds (bundler, composer, npm, cargo, ...

  7. Python虚拟环境导出包安装到另一台电脑的方法

    环境:Windows 版 Python Python 3.6.8可以用自带的命令建立虚拟环境,不用安装另外的如 virtualenv.virtualenvwrapper等工具. python -m v ...

  8. python 虚拟环境使用与管理(virtualenv)

    安装虚拟环境 pip install virtualenv 安装虚拟环境管理工具 pip install virtualenvwrapper-win 设置虚拟环境目录(虚拟环境存放位置) 默认创建的虚 ...

  9. Python程序员鲜为人知但你应该知道的16个问题(转)

    add by zhj: 没找到原文出处,只能找到转载的,文中说有17个坑,其实是16个 全文如下 这篇文章主要介绍了Python程序员代码编写时应该避免的16个“坑”,也可以说成Python程序员代码 ...

随机推荐

  1. springcloud入门系列

    关于springcloud 1.写在前面 写着写这,不知不觉springcloud写了7,8篇了,今天把文章分下类,写下感受及后面的计划吧. (1)springcloud中最最重要的是eureka注册 ...

  2. Jira 使用手册

    Date Revision version Description author 2018-06-14 V1.0.0 Isaac Zhang 2018-06-22 V1.0.1 1,添加git提交操作 ...

  3. DvaJS构建配置React项目与使用

    DvaJS构建配置React项目与使用 一,介绍与需求分析 1.1,介绍 dva 首先是一个基于redux 和redux-saga的数据流方案,然后为了简化开发体验,dva 还额外内置了react-r ...

  4. 个人永久性免费-Excel催化剂功能第49波-标准数据结构表转报表样式结果

    中国的企业信息化,已经过去了20年,企业里也产生了大量的数据,IT技术的信息化管理辅助企业经营管理也已经得到广泛地认同,现在就连一个小卖部都可以有收银系统这样的信息化管理介入.但同时也有一个很现实的问 ...

  5. 个人永久性免费-Excel催化剂功能第42波-任意字符指定长度随机函数

    日常做表过程中,难免会有一些构造数据的场景,构造数据最好是用随机的数据,如随机密码,随机英文字母.数字等.在Excel原生的随机函数Rand中,仅能处理数字的随机,且最终生成的结果也是数字类型.今天E ...

  6. Spring Boot从入门到实战(十):异步处理

    原文地址:http://blog.jboost.cn/2019/07/22/springboot-async.html 在业务开发中,有时候会遇到一些非核心的附加功能,比如短信或微信模板消息通知,或者 ...

  7. vijos p1484 ISBN号码

    #include<iostream>#include<string>#include<cctype>using namespace std;int main() { ...

  8. [leetcode] 22. Generate Parentheses(medium)

    原题 思路: 利用DFS,搜索每一种情况,同时先加"("后加")",保证()匹配正确. 最近开始学习前端,尝试用js来写. const generate = f ...

  9. Git学习(一):版本控制介绍及安装

    一.VCS(版本控制系统)的演变 1.集中式VCS的特点 1)有集中的版本管理服务器: 2)具备文件版本管理和分支管理能力: 3)集成效率较没有版本控制(如:进行文件夹标注的方式)有明显地的提高: 4 ...

  10. 小白学python-day05-IDE、格式化输出、For While循环、断点、continue、break

    今天是day05,以下是学习总结. 但行努力,莫问前程. ----------------------------------------------------------------------- ...