Python实战技术 - Python虚拟隔离环境 和 Docker技术
1. 为什么要创建虚拟隔离环境
- 在生产环境的服务器中,往往同一台主机上需要部署多个运行环境;
- 每个运行环境很可能存在不兼容的问题,比如它们使用了同一依赖的不同版本;
- 多个项目下,某个项目的升级可能导致其他项目无法使用。为了避免这种情况也要求彼此之间相互"隔离"。
2. 如何创建虚拟隔离环境
2.1. 使用 venv 创建虚拟环境
2.1.1 关于环境变量
环境变量(environment variables)是指在操作系统中用来指定操作系统运行环境的一些参数。其中环境变量Path
记录了若干个目录(文件夹),这些目录中的文件能够直接为系统所找寻。
比如在安装Python运行环境时,我们一般会将Python的安装目录以及其中的Scripts目录添加到环境变量中,以便系统找到Python.exe
以及pip.exe
两个文件。
在Windows系统中,环境变量分为用户环境变量
和系统环境变量
。所谓"系统环境变量"就是对于该系统上的所有用户都可以使用的环境变量,而"用户环境变量"就是只有当前登录用户才能使用的环境变量。
Windows上,设置环境变量的步骤如下:
1)右键单击“此电脑”
2)选择“高级系统设置”
3)点击“环境变量按钮”
4)编辑你需要编辑的环境变量:
2.1.2 使用虚拟隔离环境的一般步骤
…
2.1.3 venv虚拟隔离环境创建
详解
通过执行 venv 指令来创建一个 虚拟环境:
$ python3 -m venv /path/to/new/virtual/environment
或者,如果已经为 Python 安装 配置好 PATH 和 PATHEXT 变量:
c:\>python -m venv c:\path\to\myenv
本命令如果以 -h 参数运行,将显示可用的选项:
用法: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear] [--upgrade] [--without-pip] [--prompt PROMPT] [--upgrade-deps] ENV_DIR [ENV_DIR ...] 在一个或多个目标目录中创建虚拟Python环境。 位置参数: ENV_DIR 要在其中创建环境的目录。 可选参数: -h, --help 显示此帮助消息并退出 --system-site-packages 让虚拟环境访问系统站点包目录。 --symlinks 当符号链接不是平台的默认链接时,尽量使用符号链接而不是副本。 --copies 尝试使用副本而不是符号链接,即使符号链接是平台的默认设置。(Python3.4) --clear 在创建环境之前,删除环境目录的内容(如果它已经存在) --upgrade 如果Python已经就地升级,请升级环境目录以使用此版本的Python --without-pip 跳过在虚拟环境中安装或升级pip(默认情况下,pip是引导的) (Python3.4) --prompt PROMPT 为此环境提供一个替代提示前缀。 --upgrade-deps 升级核心依赖:pip setuptools到PyPI中的最新版本。 (Python3.9)
一旦创建了环境,您可能希望激活它,例如通过在其bin目录中提供激活脚本。
2.1.4 venv虚拟隔离环境激活
详解
激活环境不是 必须 的,激活只是将虚拟环境的二进制目录添加到搜索路径中,这样以让 “python” 命令将调用虚拟环境的 Python 解释器,可以运行其中已安装的脚本,而不必输入其完整路径。但是,安装在虚拟环境中的所有脚本都应在不激活的情况下可运行,并自动与虚拟环境的 Python 一起运行。
创建虚拟环境后,可以使用虚拟环境的二进制目录中的脚本
来“激活”该环境。
不同平台调用的脚本是不同的(须将 替换为包含虚拟环境的目录路径),可以参照下表来迅速找到自己当前系统中,创建好虚拟环境后所谓虚拟环境的二进制目录中的脚本
的所在目录位置:
平台 | Shell | 用于激活虚拟环境的命令 |
POSIX | bash/zsh | $ source /bin/activate |
fish | $ source /bin/activate.fish | |
csh/tcsh | $ source /bin/activate.csh | |
PowerShell Core | $ /bin/Activate.ps1 | |
Windows | cmd.exe | C:> \Scripts\activate.bat |
PowerShell | PS C:> \Scripts\Activate.ps1 |
当一个虚拟环境被激活时,VIRTUAL_ENV 环境变量会被设为该虚拟环境的路径。 这可被用来检测程序是否运行在虚拟环境中。
如果你这个位置觉得有些不知所云,那么继续看下去就好了。当你读完后面的实例就是到这里是怎么回事了。
2.1.5 venv建立环境常用相关命令总结
命令 | 功能 | 备注 |
sudo apt install python3-pip |
为Python3安装pip | Ubuntu等系统下 |
sudo apt-get install python-venv |
安装venv | 新版Python可以不用再安装 |
python3 -m venv .myvenv |
创建虚拟隔离环境 | 最后面是环境目录名,可以使用. 来表示建立的为隐藏目录 |
source .myvenv/bin/activate |
激活虚拟隔离环境 | 以此让 “python” 命令将调用虚拟环境的 Python 解释器 |
deactivate |
退出虚拟隔离环境 | 与激活虚拟环境是互逆过程 |
pip3 freeze >requirements.txt |
导出当前环境中安装的第三方包列表到文本文件requirements.txt | "requirements.txt"是任意取的文本文件名,你也完全可以叫其他的名字 |
pip3 install -r requirements.txt |
从文本文件requirements.txt安装其中列出的所有第三方python包 | 这里的"requirements.txt"正式上面所创建的 |
2.1.6 实例 - venv创建一个虚拟隔离环境
以下过程是在Windows平台上操作的。
(1)进入某个要作为存放虚拟隔离环境的项目文件夹,比如我放在桌面的myfiles文件夹下:
cd C:\Users\JackLee\Desktop\myfiles
(2)创建虚拟隔离环境,取名为mypython
(你也可以取其它名字):
python -m venv mypython
现在我的电脑上生成了一个名为mypython的文件夹,里面时虚拟隔离环境相关文件:
打开该文件夹:
可以看到,其中有Lib
目录和Scripts
目录,其实这就相应地是原Python这两个目录的副本。并且里面只保留了pip
等最基本的工具及其可执行二进制文件:
是的,这就意味着所谓的Python虚拟隔离环境并没有安装和使用新的Python运行环境,仍然是使用之前的Python解释器,仅仅是将由于开发者配置和安装的东西拿到环境里来,这意味着并不是与之前的环境做真正的隔离,但却能拥有一个全新的Python开发环境。这就是所谓的虚拟隔离环境
名称的由来。
接下来,就到了我们为这个似乎是全新的Python
安装一些东西了。
(3)激活虚拟隔离环境(进入环境)
进入虚拟隔离环境是通过环境中的脚本activate
来实现的。
本例中,我们的activate
脚本位于Scripts
目录下,假设当前在环境根目录,那么可以这样激活:
Scripts\activate
也可以先进入Scripts目录后再运行activate脚本:
cd C:\Users\JackLee\Desktop\myfiles\mypython\Scripts
activate
进入虚拟环境后cmd窗口显示如图:
(mypython) C:\Users\JackLee\Desktop\myfiles\mypython>
其中(mypython)
表示我们当前的cmd处在名为mypython
的虚拟隔离环境下。
(4)使用pip工具为隔离环境安装Python包
我们可以为该环境安装一个numpy包,在这个环境中的pip命令,环境变量
不再指向在系统中定义的环境变量Path中原Python下的Script目录下的pip.exe,如我的为:
C:\Users\JackLee\AppData\Roaming\Python\Python39\Scripts\
转而指向隔离环境中的pip,如上述我们建立的隔离环境中:
C:\Users\JackLee\Desktop\myfiles\mypython\Scripts
目录下的pip.exe
但是所用的Python始终都指向同一个Python解释器,即:
C:\Program Files\Python39\
(原Python安装目录)下的Python.exe
以下是安装numpy:
(mypython) C:\Users\JackLee\Desktop\myfiles\mypython>pip install numpy
安装过程完全一样:
(5)退出虚拟隔离环境:
deactivate
可以看到,已经从(mypython)
中退出了。
(6)最后可以查看pip后虚拟隔离环境中包的变化:
打开隔离环境下\Lib\site-packages
目录,与进入隔离环境使用pip安装包前对比:
可以发现多了numpy
相关包的目录。这就是我们为虚拟隔离环境安装的Python包,它不会影响到原系统目录下安装的Python第三方包。
2.2.7 通过PyCharm创建和使用Python虚拟隔离环境
3. 使用 virtualenv 创建虚拟隔离环境
在Python3.4以前Python没有内建模块venv,但是在实际开发中却广泛有创建虚拟隔离环境的需求。那是普片使用的是第三方模块virtualenv
。Python内建模块venv
与virtualenv
用法即相关概念几乎一致,因此这里不再重复介绍,只给出安装virtualenv
模块以及相关命令供大家参考。
3.1 安装virtualenv
模块
pip3 install virtualenv
3.2 使用virtualenv
模块
4. 非Python端创建隔离环境的思路介绍
使用venv
或者virtualenv
建立的隔离环境主要是用来在系统上对不同Python端进行隔离的,这样可以每次在一个虚拟隔离的环境中对特定的Python项目进行开发。这种方式简便而且也不需要多少资源就能实现多个环境的相互隔离。
不过这一方法在某些情况下也会显示出短板。比如说,我们有几个隔离的项目都需要在该系统上的MySQL数据库存储数据,但是由于某个项目的一些漏洞,可能在某些时候导致数据库的奔溃,但我们又不希望MySQL奔溃后影响到多个其他项目。这时候,基于系统层面的虚拟隔离环境Docker就诞生了。
在Docker中,一个虚拟隔离环境被称作Docker 容器
。虚拟机是虚拟了一台计算机硬件后在虚拟的硬件上安装一个系统,这种方式虽然目前在应用领域上更加强大,但也显得比较笨拙。与虚拟机不同,Docker对应用程序及其关联性进行隔离,从而构建起一套能够随处运行的自容纳单元,这一点上和Python的虚拟隔离环境是及其类似的。
安装docker
Ubuntu上安装
先更新apt 包索引
$ sudo apt-get update
安装docker
sudo apt-get install docker
Windows上安装
若在2020年以前,完全不推荐在Windows上使用Docker desktop(docker的Windows版本)。因为当时安装Docker desktop它需要使用Windows自带的虚拟机Hyper-V,并且和VMware虚拟机冲突。并且Hype-v虚拟机几乎是一个不成熟的产品,使用起来有诸多问题。不过在2020年之后,Docker desktop已经放弃了Hyper-V,转而使用WSL 2,即所谓Windows10的Linux子系统。这使得其在Windows上有着和直接在Linux系统上使用Docker有着完全一样的体验。如果你的系统支持WSL 2,,在安装Docker desktop后首次使用前将有机会看到这样的提示,那么你可能需要手动地在Windows10 程序和功能中启用并安装它。
以上如果你安装WSL遇到了问题,可以在微软官方相关页面下载最新的Linux内核安装包以及进行相应操作:
现在自己动手在Docker官网下载Docker Desktop吧:https://www.docker.com/products/docker-desktop
当你的Docker环境成功启动后,Docker首次启动好将展示带你进行简单的用法培训,单机Start
即可开始:
当然如果想直接使用,只需要将页面关闭就好了,但不能在“显示隐藏的图标”处将Docker退出。接下来,你只需要打开Windows Powser Shell 即可和在Linux系统中以完全一样的方式使用Docker。
这里我安装了一个版本号更高且是独立的PowerShell,它据说更好的性能。
安装完成后,就可以打开它并在其中执行docker命令了:
Docker镜像
在docker中,容器是可以想象为有能力处于“运行”状态的“系统”,而镜像要发挥其功能必须通过run命令制作为容器。一个容器可以保存为镜像,镜像可以理解为容器的生产图纸。
Docker Hub是用于存储docker镜像的仓库,想Linux源和Pypi源一样,它管理者众多配置好后发布的docker镜像。可以通过pull
命令从仓库中拉取需要的镜像。
如拉取一个ubuntu系统的Docker镜像:
$ docker pull ubuntu:latest
或者拉取一个在Linux系统中配置好Nginx环境的镜像:
$ docker pull nginx:latest
你甚至可以拉取一个配置好TensorFlow(基于Python jupyter)的开发环境的镜像:
$ docker pull tensorflow/tensorflow:latest
要查看pull的所有镜像,可以使用以下命令:
$ docker images
Docker容器
镜像要运行为容器,如果需要与外部进行通信的话则需要指定容器到宿主机的端口对应关系,如将绑定宿主机端口8888到docker容器内系统端口8888以创建tensorflow镜像的一个容器实例:
$ docker run -it -p 8888:8888 tensorflow/tensorflow:latest-jupyter
可以看到,将镜像实例化为容器后,将首次自动进入到容器内的系统中。这时你只需要执行exit
命令就可以回到宿主机
系统的终端,即:
exit
docker允许有多个容器,这些容器中可以有若干个处于启动状态下、若干个处于停止状态下。处于启动状态下的docker容器相当于一台开机状态下的主机,处于停止状态下的docker容器相当于一台被关闭的计算机。
你可以使用以下命令格式开启动docker容器:
$ docker start 容器id
你可以使用以下命令来停止容器:
$ docker stop 容器id
或者对一个运行中的容器进行重启:
$ docker restart 容器id
另外,docker为查看起停状态不同的容器都提供了方式。如果你只想查看当前运行中的docker容器,可以只用以下命令:
$ docker ps
但是如果你想查看的是所有docker容器,则需要添加-a
选项:
$ docker ps -a
对于不再需要的docker容器,你可以使用以下命令删除它:
$ docker rm 容器id
容器可以从Docker软件中导出到本地系统为一个文件:
$ docker export 容器id > 容器名.tar
相应地,对于一个宿主机上的docker容器压缩包,可以通过以下命令加载到docker:
$ docker import 容器完整路径或url
但是在实际开发中,我们更倾向与不直接导出导出容器。一般会将容器提交为镜像,导出导出镜像。可以使用如下命令将docker容器提交为docker镜像:
$ docker commit [OPTIONS] 容器id [镜像名:[TAG]]
以上[]
表示可选参数。其中OPTIONS
可以为:
- a 提交镜像的作者 - c 使用dockerfile指令来创建镜像 - m 提交时的文字说明 - p 在提交时,先暂停要提交的容器
一个处于运行中的docker容器,可以从宿主系统进入该容器系统执行bash命令,只需要在宿主系统中使用如下命令:
$ docker exec -it 容器id /bin/bash
docker容器与宿主机可以传输文件,这和直接在一台普通的Linux主机上拷贝文件几乎是一样的。
- 如果你需要将宿主机的某文件复制到docker容器中,可以在宿主机使用以下命令:
$ docker cp 宿主机文件完整路径 容器id:容器接收文件的目录
- 或者你想将docker容器中的文件拷贝出:
$ docker cp 容器id:容器中文件的完整路径 宿主机的接收目录