内容简介:关于我编程界的一名小程序猿,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。 联系:hylinux1024@gmail.com
关于我
编程界的一名小程序猿,目前在一个创业团队任team lead,技术栈涉及Android、 Python 、 Java 和Go,这个也是我们团队的主要技术栈。 联系:hylinux1024@gmail.com
Python
拥有大量的第三方库,引用这些库也非常方便,通过 pip install
就可以将这些第三方库安装到本地 Python
库文件目录中,然后就可以 import
到项目中,极大地提升了开发者的编码效率。
但这也带来了一个问题:当 A
项目和 B
项目同时引用 Lib
库,而 A
项目需要 Lib
版本是1.0, B
项目需要 Lib
的版本是2.0。
这样在使用 pip install
命令将 Lib
直接安装到本地全局环境中就会发生冲突,有可能会导致 A
和 B
的运行环境无法同时得到满足而运行失败。
于是虚拟环境( 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 复制代码
ALib
和 BLib
同时依赖于 sublib
,但它们依赖的版本不一样,最终在使用 pip install -r requirements.txt
也可能会 因为依赖库中的子依赖库版本不兼容而导致项目运行失败。
于是就出现了 pipenv
0x01 pipenv
说实话在这之前我一直都是使用 venv+pip
,当看到上面的问题之后,我觉得有必要了解一下 pipenv
。
1、
安装 pipenv
➜ pip install pipenv 复制代码
一旦安装完成就会引用两个文件, Pipfile
和 Pipfile.lock
。前者是用于取代 requirements.txt
文件的,后者则是用于保证依赖库的确定性和一致性。
实际上, pipenv
命令底层也是封装了 pip
和 venv
的操作,并提供了一套简单的交互命令。
创建虚拟环境
要在项目目录下(如 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 复制代码
A
和 B
模块都依赖同一个库,但依赖库的版本号不一样。这时使用 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]
复制代码
本例中我们安装了 flask
和 pytest
, pipenv 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 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Cyberwar
Kathleen Hall Jamieson / Oxford University Press / 2018-10-3 / USD 16.96
The question of how Donald Trump won the 2016 election looms over his presidency. In particular, were the 78,000 voters who gave him an Electoral College victory affected by the Russian trolls and hac......一起来看看 《Cyberwar》 这本书的介绍吧!