1 概念介绍
1.1 Python 解释器
在开始学习使用 Python 时,我们一般会直接在电脑上安装一个全局的 Python 解释器。后续也一般就是用这个解释器来运行 Python 代码。
这个 Python 解释器是有不同的版本的,比如 Python2.7 跟 Python3.7 等。
这里要了解的概念是:Python 解释器。
现在想象这样一个场景,你本地一直用 Python3.7 在学习,突然在网上发现一个很有意思的 Python 工程,下载下来之后,发现运行报错,原因是这个工程的作者当初是使用了 Python 2.7 来编写运行的。
这个时候岂不是超级无敌麻烦, 难道为了体验这个有意思的 Python 工程,就要重装我的全局的 Python 解释器?
1.2 Python 依赖
我们在写 Python 代码的时候,比如 import os 之后,那么我们的 Python 代码的运行,就依赖了这个 os 的模块。依赖其实就可以理解为是那些我们需要引用的模块、包。
像 os 这个模块是 Python 自带的,因此我们不需要额外下载安装。而像 requests 这个常用的库,我们是需要自己下载安装的。为了方便使用,就有了很多所谓的依赖的安装与管理工具,比如我们常见的pip。
这里要了解的概念是:(1)依赖(2)安装与管理工具。
现在想象这样一个场景,你从网络上下载了两个 Python 工程准备来运行学习,分别记作工程 A 跟工程 B。工程 A 依赖了 C 库的 1.0.1 版本,工程 B 依赖了 C库 的 2.0.1 版本,且 C库 的这两个版本不兼容。
这个时候岂不是超级无敌麻烦, 工程 A 跟 工程 B 就没办法同时运行了。
1.3 Python 虚拟环境
上述两个”超级无敌麻烦”的场景,在实际的团队协作与项目工作中是非常常见的.为了解决这些问题,Python 的虚拟环境机制也就应运而生。
所谓的虚拟环境,可以理解为就是创造了不同的 Python 环境,来达到 Python 解释器隔离跟依赖隔离的作用。也就是可以在同一个电脑上,使用不同的 Python 解释器,并且避免依赖冲突的问题!
有了虚拟环境,我们可以保证各个 Python 工程的运行互不干扰,也可以保证协作项目在每个协作者自身开发环境的统一。
2 Python 虚拟环境的管理方案
这块的工具可太多了,这里对常见的管理方案(工具)进行介绍跟对比。
2.1 内置 venv
在 Python 3.3 版本及以后,内置了一个模块 venv。如果你看到网络上有讲一个工具叫做 pyvenv,其实就是 venv!不过 pyvenv 的用法在 Python 3.6 就移除了。
创建虚拟环境的命令如下。
python -m venv /path/to/new/virtual/environment
此时就会以你执行上述命名的 Python 解释器版本,来创建一个虚拟环境,目录结构大致如下。
├── bin
│ ├── Activate.ps1
│ ├── activate
│ ├── activate.csh
│ ├── activate.fish
│ ├── easy_install
│ ├── easy_install-3.8
│ ├── pip
│ ├── pip3
│ ├── pip3.8
│ ├── python -> /Users/xxx/bin/python
│ └── python3 -> python
├── include
├── lib
│ └── python3.8
│ └── site-packages
└── pyvenv.cfg
具体的用法可以
python -m venv -h
查看,更多信息可参见
官方文档
的描述。
在创建了虚拟环境之后,如何使用虚拟环境?
-
在终端上使用
在终端上需要进行手动激活,比如我这边用的是 macOS ,那么就使用
source <venv>/bin/activate
来激活虚拟环境。
退出该虚拟环境则使用
deactivate
或者
exit
或者直接关闭终端。 -
在 PyCharm 等 IDE 上使用
会识别 venv 虚拟环境,可以在软件设置中修改使用的虚拟环境。
不过使用 venv 模块存在一个令人头疼的问题:如果我们有多个项目,那么就会存在多个由 venv 创建的虚拟环境,因此我们无法做到统一集中管理。
所以,Python 社区的里的其他方案也意识到了这一点,也都具备了统一在一个命令中管理虚拟环境的功能。
2.2 virtualenv
官网:https://virtualenv.pypa.io/en/latest/
我们从官网介绍可以看到 venv 的功能是 virtualenv 的一个子集,且列举了 venv 的几个不足。
- is slower
- is not as extendable
- cannot create virtual environments for arbitrarily installed python versions
- is not upgrade-able via pip
- does not have as rich programmatic API
直观上对比,venv 跟 virtualenv 都提供了环境隔离的功能,没有提供依赖安装和依赖版本解析的功能(后面介绍其他工具会提,可先不关注)。虽然 venv 只支持 Python 3.x,不支持 Python 2.x ,但随着 Python 的发展,这个也不太是问题了。
virtualenv 用法跟 venv 很类似,创建虚拟环境的命令如下。
virtualenv /path/to/new/virtual/environment
2.3 conda
Conda(conda才是包管理器,miniconda和anaconda是内置了conda的Python发行版)是环境隔离和依赖安装的一体化解决方案。
Conda 除了能安装 Python 依赖库或包之外,还能安装其他语言的一些依赖;比如有的 Python 需要调用到 C/C++ 的库,就比较适合用 Conda。
Anaconda 中不仅内置了一个 Python 解释器,同时还内置了许多常用的数据科学软件包或工具。因为自己不是从事数据科学相关领域的,所以后面也一般没有使用 Anaconda 了。
2.4 pipenv
pipenv 跟下面要介绍的 Poetry 较类似。可以理解为 Pip + pyenv + resolver + virtualenv 。其中 pip 提供了依赖安装的能力, pyenv 提供了使用多 python 解释器版本的能力,而 resolver 提供了依赖版本解析的能力。据目前了解,Pipenv 先发优势所以更加流行一些,但是 Poetry 的易用性更加,不断追赶上。
pipenv 的文档可见:https://pipenv.pypa.io/en/latest/
我在一个项目中使用了 pipenv ,常用方法有以下这些。
# 安装pipnev
pip install pipenv
# 创建虚拟环境
pipenv install # 虚拟环境如果不存在的话,会自动创建
pipenv --python 3.8 # 可以指定python版本。 pipenv 会自动扫描系统寻找合适的版本信息,如果找不到的话,同时又安装了 pyenv, 它会自动调用pyenv下载对应的版本的python
# 查看虚拟环境
pipenv --venv
/Users/userisme/.local/share/virtualenvs/test_project-wL5os1_R
# 激活虚拟环境
(base) userisme-MC0:test_project userisme$ pipenv shell
Launching subshell in virtual environment...
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ . /Users/userisme/.local/share/virtualenvs/test_project-wL5os1_R/bin/activate
# 退出虚拟环境
(test_project) bash-3.2$ exit
exit
(base) userisme-MC0:test_project userisme$
# 安装依赖到虚拟环境
pipenv install
pipenv install requests==2.13.0 # 安装指定版本
# 依赖安装
pipenv install # 会自动安装Pipfile中记录的依赖
# 其他
pipenv install --dev # 可区分开发依赖
pipenv graph # 图形显示包依赖关系
pipenv uninstall --all # 删除所有的安装包
pipenv install -r path/to/requirements.txt # 安装requirements.txt中的依赖
# 从Pipfile和Pipfile.lock文件来生成requirements.txt
pipenv lock -r # 生成requirements.txt文件
pipenv lock -r -d # 生成dev-packages的requirements.txt文件
2.5 poetry
poetry 使用
pyproject.toml
来做依赖说明(还有其他作用,这里不涉及就不提了)。poetry 除了依赖管理,还具备了打包的能力,不需要额外安装 setuptools 来发布你的安装包。
基础的用法可以查看文档:https://python-poetry.org/docs/basic-usage/
大概看了一眼,讲的还是比较细致了:
- 包含了常见命令跟常见的使用场景
-
如果看到版本号限定为
^2.1
,其代表的意思是 (>= 2.1.0 , < 3.0.0)。 - 需要注意的是,现在最新版本的 poetry 是不支持 Python2.7 了。大家还是使用 Python 3.+ 吧。
2.6 pdm
大家可以看 github上 的介绍:https://github.com/pdm-project/pdm
这个作者是中国人,其本身也是 pipenv 的维护者~
2.7 大致结论
虽然 PDM 我还没用过,但看了下他的 blog ,其观点我很赞同: 其实目前以上的 Python 的工具,基本上就是围绕着虚拟环境管理、依赖管理、打包发布这三块在解决问题,提升用户体验。不同工具有其侧重点跟覆盖范围,大家还是全凭需求来选择!
如果你只是简单了解学习下 Python ,看起来是使用自带的 venv 就行。
如果你是做科学计算的库,可能较适合用 conda(Anaconda、miniconda)
如果是同时参与多个 Python 项目开发的,需要使用虚拟环境的,比较推荐用 Poetry 。
如果你都不喜欢,你完全可以弄个虚拟机或 Docker ,然后随便搞。
3 关于项目协作开发中的依赖问题
项目的依赖应当明确地写在项目的依赖文件中。通常在实际的开发、测试、生产环境中,为了保持依赖完全一致,通常是将依赖信息固定写入到 requirements.txt 中。使用命令如
pip freeze > requirements.txt
这里随便提一下 install_requires 这个东西,由于个人不了解,就不多讨论了。它跟 requirements 的比较可以参考:https://packaging.python.org/en/latest/discussions/install-requires-vs-requirements/ 。
4 参考文档
这篇文章个人感觉内容丰富,值得一看。
细数 Python 虚拟环境的管理方案