摘要:本文介绍Python中常用虚拟环境的用法。
文章说明
文章作者:鴻塵
参考资料:
- Python中文指南第十二章:虚拟环境
- Python标准库venv-创建虚拟环境
- Python 虚拟环境的使用-virtualenv/virtualenvwrapper、pycharm使用
- Runoob Python tutorial-虚拟环境和包-pyvenv
- Python为什么要使用虚拟环境-Python虚拟环境的安装和配置-virtualenv
- 知乎:最全的Python虚拟环境使用方法-virtualenv/conda/pipenv
文章链接:Python虚拟环境
文章说明接:这片文章是复制的Python中文指南第十二章:虚拟环境,后面再慢慢整理吧慢慢改吧。
虚拟环境
所谓虚拟环境(virtual environment),是指一种采用协作式隔离的运行时环境,允许 Python 用户和应用程序在安装和升级 Python 分发包时不会干扰到同一系统上运行的其他 Python 应用程序的行为。
使用虚拟环境有以下优点:
- 使不同应用开发环境独立;
- 环境升级不影响其他应用,也不会影响全局的python环境;
- 可以防止系统中出现包管理混乱和版本的冲突;
- 不同环境中Python依赖包相互独立,互不干扰。
管理Python版本和环境的工具有很多,常用的有以下几种:
venv
:Python自带的模块,virtualenv
:virtualenvwrapper
:pipenv
:pyvenv
:
12.1【虚拟环境】为什么要有虚拟环境?
虚拟环境的意义,就如同虚拟机 一样,它可以实现不同环境中Python依赖包相互独立,互不干扰。
举个例子吧。
假设我们的电脑里有两个项目,他们都用到同一个第三方包,本来一切都顺利。但是由于某种原因,项目B由于某些原因要使用这个第三方包的一些新特性(新版本才有),而如果就这样贸然升级了,对项目A的影响我们无法评估,这个时候我们就特别需要有一种解决方案可以让项目A和B,处于两个不同的Python环境中。互不影响。
为了方便大家对虚拟环境有个认识,我列举了下其优点:
- 使不同应用开发环境独立
- 环境升级不影响其他应用,也不会影响全局的python环境
- 可以防止系统中出现包管理混乱和版本的冲突
市场上管理 Python 版本和环境的工具有很多,这里列举几个:
p
:非常简单的交互式 python 版本管理工具。pyenv
:简单的 Python 版本管理工具。Vex
:可以在虚拟环境中执行命令。virtualenv
:创建独立 Python 环境的工具。virtualenvwrapper
:virtualenv 的一组扩展。
工具很多,但个人认为最好用的,当属 virtualenvwrapper
,推荐大家也使用。
12.2 【虚拟环境】方案一:使用 virtualenv
1. 安装virtualenv
由于 virtualenvwrapper 是 virtualenv 的一组扩展,所以如果要使用 virtualenvwrapper,就必须先安装 virtualenv。
基本使用
由于virtualenv创建虚拟环境是在当前环境下创建的。所以我们要准备一个专门存放虚拟环境的目录。(以下操作在Linux在完成,windows相对简单,请自行完成,有不明白的请微信与我联系。)
创建
1 | ## 准备目录并进入 |
进入/退出
1 | $ cd /home/wangbm/Envs |
删除
删除虚拟环境,只需删除对应的文件夹就行了。并不会影响全局的Python和其他环境。
1 | $ cd /home/wangbm/Envs |
注意:
创建的虚拟环境,不会包含原生全局环境的第三方包,其会保证新建虚拟环境的干净。
如果你需要和全局环境使用相同的第三方包。可以使用如下方法:
1 | ## 导出依赖包 |
2. 使用 virtualenvwrapper
virtualenv 虽然已经相当好用了,可是功能还是不够完善。
你可能也发现了,要进入虚拟环境,必须得牢记之前设置的虚拟环境目录,如果你每次按规矩来,都将环境安装在固定目录下也没啥事。但是很多情况下,人是会懒惰的,到时可能会有很多个虚拟环境散落在系统各处,你将有可能忘记它们的名字或者位置。
还有一点,virtualenv 切换环境需要两步,退出 -> 进入。不够简便。
为了解决这两个问题,virtualenvwrapper就诞生了。
安装
1 | ## 安装 - Linux |
配置
先find一下virtualenvwrapper.sh
文件的位置
1 | find / -name virtualenvwrapper.sh |
若是 windows 则使用everything 查找 virtualenvwrapper.bat 脚本
1 | D:\Program Files (x86)\Python38-32\Scripts\virtualenvwrapper.bat |
在~/.bashrc 文件新增配置
1 | export WORKON_HOME=$HOME/.virtualenvs |
若是 windows 则新增环境变量:WORKON_HOME
基本语法:
mkvirtualenv [-a project_path] [-i package] [-r requirements_file] [virtualenv options] ENVNAME
常用方法
1 | ## 创建 |
其他命令
1 | ## 列出帮助文档 |
更多内容,可查看 官方文档
https://virtualenvwrapper.readthedocs.io/en/latest/command_ref.html
3. 实战演示
以上内容,是一份使用指南。接下来,一起来看看,如何在项目中使用虚拟环境。
如何使用在我们的开发中使用我们的虚拟环境呢
通常我们使用的场景有如下几种
- 交互式中
- PyCharm中
- 工程中
接下来,我将一一展示。
3.1 交互式中
先对比下,全局环境和虚拟环境的区别,全局环境中有requests包,而虚拟环境中并未安装。
当我们敲入 workon my_env01
,前面有my_env01
的标识,说明我们已经处在虚拟环境中。后面所有的操作,都将在虚拟环境下执行。
3.2 工程项目中
我们的工程项目,都有一个入口文件,仔细观察,其首行可以指定Python解释器。
倘若我们要在虚拟环境中运行这个项目,只要更改这个文件头部即可。
现在我还是以,import requests
为例,来说明,是否是在虚拟环境下运行的,如果是,则和上面一样,会报错。
文件内容:
1 | #!/root/.virtualenvs/my_env01/bin/python |
运行前,注意添加执行权限。
1 | $ chmod +x ming.py |
好了。来执行一下
1 | $ ./ming.py |
发现和预期一样,真的报错了。说明我们指定的虚拟环境有效果。
3.3 PyCharm中
点击 File - Settings - Project - Interpreter
点击小齿轮。如图点击添加,按提示添加一个虚拟环境。然后点 OK 就可以使用这个虚拟环境,之后的项目都会在这个虚拟环境下运行。
12.3 【虚拟环境】方案二:使用 pipenv
以前一直使用pip+virtualenv+virtualwrapper管理模块和环境, 但是virtualwrapper在windows上使用不太方便,而且包和环境分开管理确实经常不记得哪个是哪个了。
为什么 会推荐 pipenv 呢?
- 它是
virtualenv
和pip
的合体,可以合起来使用; - 使用
Pipfile
和Pipfile.lock
替代requirements.txt
- 可以使用
pipenv graph
很方便的看出包的依赖关系。 - 通过加载
.env
文件简化开发工作流程
1. 安装pipenv
如果你的电脑上没有安装 pipenv,可以使用如下方法安装
1 | # mac |
如果你的电脑是 windows 的。
需要将如标示路径,加入到 环境变量 PATH 中。
然后需要重启一下,CMD 终端才能够刷新环境变量。
2. 创建虚拟环境
DjangoWebBlog 是我们的项目目录,进入这个目录下创建虚拟环境
1 | mkdir DjangoWebBlog && cd DjangoWebBlog |
你也可以指定版本创建
1 | pipenv --two # 相当于 pipenv --python /usr/bin/python2 |
这边以安装 python2 版本的虚拟环境为例说明。
如果你原项目使用的是 requirements.txt 这个管理包的方式,这时候执行 pipenv --tow
创建一个虚拟环境后,会找到 requirements.txt ,并根据这里面的依赖包生成 Pipfile文件。
3. 查询虚拟环境
1 | # 返回项目的路径 |
演示如下:
4. 操作虚拟环境
1 | # 进入这个虚拟环境 |
执行 pipenv shell
就可以进入这个虚拟环境,在头部会有虚拟环境的标识名称。有这个标识,说明已经进入虚拟环境。
1 | ## 在当前虚拟环境中运行 |
5. 虚拟环境包管理
1 | # 安装一个本地包(setup.py)到虚拟环境(Pipfile) |
6. 其他命令
1 | # 创建一个包含预发布的锁文件: |
打印该虚拟环境下所有包的依赖关系图
有的python第三方包旧版本会有安全漏洞,使用 pipenv check 可以检查安全漏洞。
12.4 【虚拟环境】方案三:使用 pipx
1. 什么是 pipx
pipx 是一款用于帮助你安装和运行那些用 python 编写的终端程序,它类似于 macOS 上的 brew,Ubuntu 上的 apt,CentOS 上的 yum。
pipx 依赖 pip 和 venv,它只能在 python 3.6+ 的 Python 版本中才能使用。
默认情况下,pipx 和 pip 一样会从 pypi 上安装包,同时 pipx 也能像 pip 一样从本地、git仓库、wheel 文件中安装包。
为了避免你在安装 python app时,由于多版本而导致冲突,通常我们会使用 venv 或者 virtualenv 新建一个虚拟环境,然后将 app 安装到虚拟环境中。
后续你对这个 app 的管理操作,都得先进入这个虚拟环境。
发现没有?好像有点麻烦。
pipx 的存在使这个流程变得更加舒畅,使用 pipx 你可以无需关注虚拟环境的存在,并在你的机器上安装多个版本的 python app。
2. 安装使用
安装 pipx
1 | python3 -m pip install --user pipx |
使用 Pipx 需要注意两个路径
- 二进制文件的保存位置:默认是
~/.local/bin
,可使用环境变量PIPX_BIN_DIR
进行更改,或者执行如下命令(python3 -m userpath append ${you_path}
) - 虚拟环境的保存位置:默认是
~/.local/pipx
,可使用环境变量PIPX_HOME
进行更改
在我安装好 pipx ,准备使用的时候,发现全局找不到 pipx 这个命令。
按照如上图所示,难道使用全路径执行命令?
不,怎么都觉得不太对劲。。
想要解决这个问题,其实很简单,有两种方法(两种都可以,我演示使用的第一种方法):
- 添加个软链接指向刚刚那个全路径就好啦
- 将这个路径添加到 PATH 中
/Users/MING/Library/Python/3.9/bin/
1 | ln -s /Users/MING//Library/Python/3.9/bin/pipx /usr/local/bin/pipx |
软链接建好后,就可以直接使用 pipx
的命令啦。
刚刚我使用 pipx 安装了 youtube-dl 后,其实并没有将这个 youtube-dl 安装到系统全局的 Python 环境中。
还记得最开始,我强调过两个非常重要的路径吗?
现在来看一下,这个路径下面都有哪些东西?
从截图上可以看出
- pipx 在
~/.local/pipx/venvs
目录下新建了个名叫youtube-dl
的虚拟机环境 - 并将
youtube-dl
安装到这个虚拟机环境中 - 然后在
~/.local/bin
的目录下新建一个软链接,指向这个虚拟环境中 - 这样
youtube-dl
就变成全局的工具啦。
为了避免你新安装的 youtube-dl 与全局的冲突,你也可以指定 pipx 的命令来运行 youtube-dl
1 | pipx run youtube-dl --no-check-certificate https://www.bilibili.com/video/BV1jK4y1h7uA |
运行效果如下:
pip run 也可以直接执行在线的 python 脚本
1 | pipx run https://gist.githubusercontent.com/cs01/fa721a17a326e551ede048c5088f9e0f/raw/6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py |
3. 查看包
查看已安装过的包
1 | pipx list |
4. 安装包
下载最新版本的 python 包,并安装到新建的虚拟环境中
1 | pipx install <PACKAGE> |
4. 运行APP
pipx run
后面可接一个包的 url 链接,会将这个包下载下来并运行,也可以接已安装过的应用名来直接运行它
1 | pipx run <PACKAGE_URL/APP> |
如果一个 app 有多个版本,那么可以通过 spec
指定版本号
1 | pipx run --spec PACKAGE==1.0.0 app |
更神奇的是,pipx 支持指定 git 代码仓库直接运行
1 | pipx run --spec git+https://github.com/psf/black.git black |
5. 升级包
升级某个包
1 | pipx upgrade <pkg> |
升级全部包
1 | pipx upgrade-all |
6. 卸载包
卸载某个包
1 | pipx uninstall <pkg> |
卸载全部包
1 | pipx uninstall-all |
重装全部包
1 | pipx reinstall-all |
7. 使用 pip
每执行一次 pipx install 就会新建一个虚拟环境,那我们有没有办法管理这些虚拟机环境呢?
比如我想看这个虚拟环境里安装了哪些包?
使用如下命令就可以像使用 pip 一样,来管理 pipx 的虚拟环境
1 | pipx runpip <env_name> <args> |
效果如下
8. 其他
执行 pipx completions
可以启用 pipx 的补全说明。
对于不同的终端开启方式不一样,我使用的是 zsh,方法是
1 | autoload -U bashcompinit |
我安装好后,可以使用 tab 键进行命令补全。
执行 pipx ensurepath
可以确保 ~/.local/bin
这个重要的目录,已经放入到 $PATH
的变量中。
9. pipx vs pip
pipx 只是解决 pip 的一个痛点,因此他的适用场景比较单一,它只适用于安装和运行那些有提供命令行入口的app。
- pip 适用于大多数的 Python 版本,而 pipx 需要 Python 3.6+ 才可以使用
- pipx 依赖 pip 和 venv,可以使用 pip 安装pipx ,反过来则不行。
- pip 和 pipx 默认都是从 pypi 上安装包
- pipx 在安装和管理 cli 应用程序时,比 pip 更灵活,它可以在允许在隔离环境中安装和运行 Python 应用
10. 参考文章
12.5 【虚拟环境】方案四:使用 poetry
1. 安装 poetry
poetry提供多种安装方式,个人推荐从以下2种方式中选择:
方式一:(推荐)使用在线脚本进行安装,是最为推荐的安装方式
1 | curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python |
方式二:(pip) 官方不建议这么做,因为有可能会造成依赖冲突,可以考虑用 pipx 或 pipsi
1 | pip install --user poetry |
安装后,可以使用如下命令检测是否可用
1 | poetry --version |
2. 创建项目
如果你是在一个已有的项目里使用 Poetry,你只需要执行 poetry init 命令来创建一个 pyproject.toml 文件:
1 | poetry init |
而如果是新建 一个项目,可以使用这个命令
1 | poetry new demo-priject |
运行完后,在当前目录下就会多一个 demo-project
的目录,这个目录下的文件结构如下
1 | tree demo-priject |
如果要把项目代码放入到 src 目录下,在创建项目时,可以加上 --src
参数。
3. 创建虚拟环境
使用 poetry install 命令创建虚拟环境(确保当前目录有 pyproject.toml 文件):
1 | poetry install |
这个命令会读取 pyproject.toml 中的所有依赖(包括开发依赖)并安装,如果不想安装开发依赖,可以附加 —no-dev 选项。如果项目根目录有 poetry.lock 文件,会安装这个文件中列出的锁定版本的依赖。如果执行 add/remove 命令的时候没有检测到虚拟环境,也会为当前目录自动创建虚拟环境。
4. 使用虚拟环境
创建虚拟环境后,如果想要在虚拟环境下执行命令,比如去执行脚本,去使用 pip list 等等。
可以在项目目录下,使用如下命令
1 | poetry run <commands> |
比如我查看该虚拟环境中安装了哪些包
1 | poetry run pip list |
再比如我想在该虚拟环境下执行 app.py
1 | poetry run python app.py |
每次在虚拟环境下做点啥事,命令前面都要加上 poetry run
,有点太麻烦了。
这时可以使用下面这条命令,直接激活当前的虚拟环境
1 | poetry shell |
5. 包的管理
安装包
1 | poetry add <pkg> |
添加 —dev 参数可以指定为开发依赖
1 | poetry add pytest --dev |
查看所有安装的依赖包
1 | poetry show |
加上 --tree
可以查看他们的依赖关系
1 | poetry show --tree |
加上 --outdated
可以查看可以更新的依赖
1 | poetry show --outdated |
如果要更新依赖可以执行这个命令
1 | # 更新全部 |
想卸载某个包,用这个命令
1 | poetry remove foo |
6. 常用配置
Poetry 的配置存储在单独的文件中,比 Pipenv 设置环境变量的方式要方便一点。配置通过 poetry config 命令设置,比如下面的命令可以写入 PyPI 的账号密码信息:
1 | poetry config http-basic.pypi username password |
下面的命令设置在项目内创建虚拟环境文件夹:
1 | poetry config settings.virtualenvs.in-project true |
另一个常用的配置是设置 PyPI 镜像源,以使用豆瓣提供的 PyPI 镜像源为例,你需要在 pyproject.toml 文件里加入这部分内容:
1 | [[tool.poetry.source]] |
不过经过测试 Poetry 会使用 pip.ini 设置的 PyPI 镜像,而且豆瓣的源好像很久没更新了(创建虚拟环境安装的默认依赖里 importlib-metadata==0.20 找不到),这篇文章列出了一些其他国内的 PyPI 源。
7. 参考文章
12.6 【虚拟环境】方案五:使用 venv
在前面介绍的几种方法中,都需要借助第三方模块来完成虚拟环境的管理。
但其实在 Python 3 中就自带了一个专门用门管理虚拟环境的模块,它叫 venv
。
1. 创建虚拟环境
venv
后可以接一个目录(如果此目录不存在,会自动创建)用于创建你的虚拟环境,他可以是绝对路径,也可以是相对路径。
1 | # mac or linux |
使用 venv 创建虚拟环境的速度非常快,大概只需要两三秒的样子。
创建完成后,在你所指定的目录下会有一个 pyvenv.cfg
的配置文件,它记录着虚拟环境的基本信息,包括你使用的 Python 的家目录,还有当前虚拟环境的 Python 版本,是否开启使用系统的 site-packages 模块,如果开启了,那么当你就可以直接使用系统中已经装过的第三方模块,但是你在虚拟环境下装的模块就不能被其他地方的程序使用。
1 | home = /usr/local/bin |
如果你的环境中有 Python 3.8 也有 Python 3.9 ,那该怎么办呢?
只要你在创建时,用你预期版本的 Python 去执行就好啦
1 | python3.8 -m venv [venv_dir] |
可如果你的环境中有两个 Python 3.9 呢?你想使用不在 PATH
的中的 Python 去创建,就要用绝对路径去创建了。
1 | /usr/local/bin/python3 -m venv [venv_dir] |
2. 进入创建环境
进入虚拟环境的方法,对比之前介绍的方案,venv 的方法就相当原始了。
如果你使用 Windows ,那么在 cmd 下进行 Scripts
目录,执行 activate.bat
1 | # cmd.exe |
如果你使用PowserShell激活虚拟环境出现如下错误,那要先执行这个命令:Set-ExecutionPolicy RemoteSigned
,再按 Y
而如果你使用的 Mac 或者 Linux,那么直接执行下面命令就行
1 | source bin/activate |
执行完后,若在你的命令行下有 demo
字样(之所以是 demo ,因为我们创建时的目录名就是 demo),说明你已经处于虚拟环境下。 由于虚拟环境是全新的干净环境,此时你使用 pip list
,会看到啥包都没有,只有最基本的 pip 和 setuptools 。
3. 退出虚拟环境
退出虚拟环境,无论是 Windows 、 Mac 、 还是 Linux ,方法都是同一条命令。退出后,你的虚拟环境名称(如上面的 demo
)也会消失。
1 | deactivate |
4. 总结一下
venv
是 Python3 中自带的虚拟环境管理工具,不需要额外安装,功能简单,用法也简单。但是它不能像 poetry 和 pipenv 用于项目的管理,因此 venv 建议只做了解,在一些简单的场景中可以使用,如果是复杂的项目中,可以直接上 poetry 和 pipenv。