1.2 Python开发环境

在学习Python的初级阶段,为了方便使用,开发者往往选择Windows系统作为开发环境。而大数据开发往往涉及数据的获取和存储、服务的部署、搭建大数据集群,以及在同时使用多台服务器协同计算时的任务调度和负载均衡等,从集群化、效率及扩展性等方面考虑的话,建议使用Linux+Docker+Jupyter的解决方案。下面介绍在Windows和Linux两种环境下创建Python开发环境。

1.2.1 Windows环境

1.安装Python工具

在Windows系统中安装Python环境,需要先从Python官网下载安装包。

选择其最新版本,在Windows环境下建议下载“Windows x86-64 executable installer”可执行的安装包,在安装时建议选择“Add Python 3.7 to PATH”,以便之后在Windows命令行cmd环境下也可直接使用Python及相关工具,设置界面如图1.1所示。

图1.1 Python安装界面

安装完成后,就可以在命令行通过命令“python”或者通过开始菜单的程序打开Python界面。Python安装包中自带包管理工具pip,它具有对Python包的查找、下载、安装、卸载等功能,使用它可以安装Python的第三方软件,如安装基于Web的Python集成开发环境Jupyter。

运行Jupyter Notebook后会自动启动默认浏览器,通过URL连接Python开发环境,输入的命令将被传到后台服务器进行处理,处理后将其结果返回浏览器显示。Jupyter工具将在后续章节中详细介绍。

注意:有些版本的浏览器不支持Jupyter,建议使用Firefox或Chrome浏览器。

2.安装Anaconda工具

使用“pip”命令可以安装大多数的Python库和工具,但需要手动输入命令逐个安装,比较麻烦。Anaconda是一款集成工具,包含了Python,Jupyter,Spyder,conda等开发工具,以及Numpy,Sklearn,Pandas,Matplotlib,Seaborn,Scipy等常用的Python科学计算第三方库,共180多个工具。其安装包有500多兆,支持Windows,Linux及mac OSX操作系统,可从Anaconda官网下载最新版本。

在安装过程中,建议在Option界面勾选“Add Anaconda to the system PATH environment variable”,以便之后在Windows命令行cmd环境下也可直接使用Python,Jupyter等工具,设置界面如图1.2所示。

图1.2 Anaconda安装界面

安装完成后,在开始菜单的程序中可以看到Anaconda3,其子菜单中包括了Jupyter,Spyder等软件,在cmd命令行中也可通过命令启动Python,Jpython及Spyder工具。对于初学者建立试验环境,Anaconda一次性安装了大多数的包,这省去了安装常用第三方库的操作,以及解决了包之间依赖关系的问题。

Anaconda支持图形界面的包管理工具Anaconda Navigator,这易于初学者安装工具包。同时,它也支持命令行Anaconda Prompt,通过使用conda命令支持更加灵活的包管理。在Windows系统中开发Python,除了Jupyter也可以使用Anaconda中安装的Spyder集成开发环境。Spyder是由Python的作者编写的一款简单的开发环境,用法类似于MATLAB。常用的Windows Python开发环境还有PyCharm。

1.2.2 Linux环境

作为高级开发人员,需要设计的不仅包括代码的编写,而且还包括数据相关的整个流程,即从定义问题到可行性分析,到系统架构设计软硬件资源的部署,以及数据的获取、存储、分析、建模,最终将分析研究成果产品化。

大数据开发不仅涉及使用程序分析和处理数据,还涉及整个数据处理流程的方方面面。当业务量和数据量达到一定量级后,就需要设计集群解决方案,即部分机器用于存储、部分机器用于运算、部分机器用于提供服务,或当从外部采集数据时要考虑到系统的安全性和稳定程度,还需要规划存储和主要调度服务的备份。

Linux是高性能计算(High Performance Computing,HPC)首选的操作系统。在2018年6月的超级计算机500强榜单中,所有的机器都运行Linux系统。由于Linux具有开源的特性,因此其上有大量软件可供选择,而开源又使开发者在使用时不仅能知其然,还能知其所以然。对于一些说明文档不多的软件,也可通过阅读源码了解其功能和工作流程,必要时还可以修改、定制。从成本方面来看,Linux上的大量免费软件都能更好地控制开发成本。从集群方案方面来看,Linux在服务集群解决方案方面已经相当成熟。从技术支持方面来看,开源社区、企业和个人开发的支持率也比较高,相关的文档和参考资料很多。从运行效率来看,Linux支持从内核到上层应用的各层级的定制和剪裁,这使得各个节点能更加专注于其自身功能,也使其运行效率更高且更加安全。

云服务也是大数据常用的解决方案,可按需租用,有的云计算服务还按小时租用,使用云服务可以极大地节约服务器的采购和维护成本与时间成本。云服务一般都支持Linux和Windows两种系统。相对来说,Windows占用资源更多,同等业务就需要更高的配置,而从本地登录到云端服务时,Windows需要远程桌面或者类似的工具,信息都基于图片或视频数据压缩传输。而Linux在支持图形界面的同时,也支持ssh命令行连接,以字符方式传输。因此,无论是效率还是传输数据量,Linux都远远优于Windows。可以说,Linux是公认的服务器解决方案。

由于Linux也是大数据开发必备的系统,因此,读者需要掌握其基本操作。本书涉及了数据分析相关的集群知识,尤其在学习第5章数据库及数据仓库的访问和修改时,建议安装Linux系统,以便调试本书中的所有程序(除第5章外的其他程序,也可以在Windows系统中正常运行)。

如果读者想深入学习Linux操作系统,最好将它直接安装到计算机硬件上,这样能让系统运行得更高效。对于不熟悉Linux系统的读者来说,需要先学习硬盘分区并保留计算机中原有的操作系统,这相对比较复杂,容易误操作,因此,建议先用虚拟机方式安装。

虚拟机就像是安装了另一台计算机,其与宿主机(安装虚拟机软件的计算机)的软件隔离,方便环境的迁移,使用虚拟机可以部分解决环境不一致和现场软件安装的问题。

下面介绍在Windows环境下安装Linux虚拟机的基本方法。在Windows系统中只要是Windows XP以上系统都可正常安装,虚拟机选用VirtualBox或者VMware。本例中使用了VirtualBox-5.1.26版本,Linux系统使用了Ubuntu 16.04。先下载Ubuntu安装盘的ISO镜像文件和VirtualBox软件,安装后,VirtualBox界面如图1.3所示。

图1.3 VirtualBox虚拟机界面

注意:Linux的版本可以使用Ubuntu,也可以使用CentOS,不用过分纠结它们的具体版本,因为后期开发的相关软件都安装在Docker中,和操作系统关系不大。

安装方法如下:先新建虚拟电脑,选择其操作系统类型为Linux,版本为Ubuntu。然后在内存大小界面设置其内存在2G以上(一般为宿主机内存的一半),在虚拟硬盘界面选择“现在创建虚拟硬盘”创建“vdi(VirtualBox磁盘镜像)”,并选择“动态分配”其大小,这样可使虚拟机随着存储数据的增加逐渐占用存储空间,选择虚拟盘的位置并建立空间为20G以上(建议为50G)的虚拟硬盘,完成创建虚拟机。

选择已创建的虚拟机,在其设置界面的存储选项卡中添加虚拟光驱,选择下载Ubuntu安装盘的ISO文件,设置完成后启动该虚拟机,即可看到虚拟机从光盘启动,启动后的界面显示如图1.4所示。

图1.4 Ubuntu安装界面

在左侧选择语言为“中文(简体)”、右侧选择“安装Ubuntu”后,在“准备安装”界面选择“继续”;在“安装类型”界面,如果之前未安装过Ubuntu系统,并且在虚拟机中安装,则选择其默认选项“清除整个磁盘并安装”,此时的“清除”指清除虚拟机中的内容,不会影响Windows系统。对于熟悉Linux的开发者或者是在非虚拟机中安装,可以选择“其他选择”,手动设置分区,这样可以使Linux与计算机中其他操作系统并存,在此不深入讨论。本例中选择其默认选项,点击“现在安装”,并在确认框中选择“继续”。

接下来选择时区为“上海”,键盘布局为“汉语”,并按提示输入用户名和密码。此后,系统开始安装,一般在等待几分钟到十几分钟后安装结束,重启即可启动新安装的Ubuntu系统。

在Linux系统中,主要使用终端通过命令行的方式安装服务和运行程序。在桌面的左上角的“搜索您的计算机”中输入“gnome-terminal”找到终端,打开即可输入命令,终端界面如图1.5所示。

图1.5 Ubuntu操作系统终端界面

在安装好系统后,虚拟机和宿主机还不支持共用剪切板、文件共享,以及根据窗口大小自动调节分辨率等功能,这就需要安装增强功能。在虚拟机的设备菜单中,选择“安装增强功能”,安装完重新启动,然后在设备菜单的共享粘贴板子菜单中选择双向,剪切板等功能就可以正常使用了。

注意:本书下文中的操作系统环境默认为Ubuntu环境,不再涉及Windows及VirtualBox虚拟机的调用关系。

1.2.3 Docker环境

由于程序开发和程序部署往往不在同一台计算机上,而很多时候还需要按照客户要求定制系统,而我们编写的程序经常依赖于其他Python库及系统底层软件,这时还需要注意其各个版本之间的依赖关系。由于安全和保密的原因,一些客户部署场地需要内外网隔离使得软件不能联网自动安装,必须根据具体环境复制安装大量软件,这大大增加了现场实施的难度,以及发生错误的可能性。

虚拟机适用于在一个系统中安装另一个操作系统,即在一台机器上同时使用两个操作系统。由于虚拟机需要启动整个系统,因此往往占用较多资源,且启动时间长。

目前,搭建集群中的各种服务基本都使用Docker。Docker是包含虚拟系统、程序运行、打包、管理等方法的一整套解决方案。它可以将具体的应用从基本系统中剥离出来,如可以将MySQL数据库、前端服务、模型预测分别打包成不同的Docker镜像。在集群中,当需要在某一台机器上运行数据库时,就可以把MySQL镜像复制到该物理机器上运行。

相对于虚拟机,Docker的启动时间更快,占用资源更少,与在宿主机上直接安装和运行软件差别不大。在启动Docker时,可指定运行其中的某种应用程序,同时Docker还提供工具快速建立Docker镜像。镜像的版本管理工具可以让使用者快速切换到某一版本,且占用更少的存储空间。

网络上有很多其他人发布的Docker镜像,下载到本地后无须考虑其宿主机的软硬件环境即可直接使用,这可以大大减少运维的工作量。

即使有系统运维工程师搭建系统,而作为大数据开发人员也需要掌握基本的Docker技能。Docker的功能很多,有专门的书籍介绍其功能和用法,本书第5章中介绍的Python访问数据库及数据仓库都是基于数据库和数据仓库的Docker镜像实现的。本小节只是从实用的角度介绍Docker的基本原理,以及最常用的使用方法和使用场景,以便保证读者能正常使用Docker。

1.安装Docker环境

下面介绍Docker工具的基本安装和使用方法,首先在Ubuntu系统中安装Docker工具。在Ubuntu系统中,使用“apt-get”命令安装软件、“sudo”命令将当前用户切换为超级用户“root”,具体命令如下:

安装完Docker后,就可以使用“docker”命令了。此时,还只能用“root”身份使用大多数的Docker命令,如果想让某个用户操作Docker,则需要将其加入“docker”组。

最后一条命令将启动名为“ubuntu”的Docker镜像。如果本地不存在“ubuntu”镜像,则会从官网下载。从命令行中可以看到提示符与之前不同,此时就进入了Docker所启动系统的命令行,说明已经进入了该镜像,并以交互方式运行“bash”命令(bash是Linux Shell程序),这时可以使用“exit”命令退出Docker环境。

通过上述操作可以看到,使用Docker只需要一个命令即可安装和启动各种Docker环境,比使用虚拟机方便得多。Docker镜像是一个只有几十兆的小系统,此时可以用“apt-get”命令安装一些软件来构造Docker内部环境。

注意:后面还会用到该容器,建议不要退出,先使用“Ctrl+Shirt+T”组合键以标签页的方式打开另一个终端进行后续操作。

2.Docker的C/S模式

从上面的“service docker restart”命令可以看出,Docker是C/S模式,C即Client(客户端),S即Server(服务端),服务端与客户端之间通过Socker通讯。服务端(即Docker系统)在后台运行,客户端用“docker”命令与服务端通讯,通过以下命令可显示Docker系统信息。

3.容器的相关操作

如果把Docker看成虚拟机,容器则是虚拟机的运行实例,简单地说就是正在运行着的虚拟电脑。容器是Docker的重要概念,对Docker的操作主要是围绕它进行的。下面介绍容器的相关操作。

(1)创建和启动容器,“docker run”命令可同时创建和启动容器。在安装Docker环境时,用“run”命令启动容器。下面介绍run命令的使用方法和主要参数:

其主要参数如下:

◎-d:后台运行容器,并返回容器ID。

◎-i:以交互模式运行容器,通常与-t同时使用。

◎-t:为容器重新分配一个伪输入终端,通常与-i同时使用。

◎-p:将容器端口映射到主机端口(如-p 8890:8888是把容器中的8888端口映射到宿主机8890端口)。

◎-v:将主机目录映射到容器中(如-v/data:/tmp/a是把主机目录/data映射到容器中的目录/tmp/a下;在同一命令行中可使用多组-v映射多个目录)。

◎--ip:指定IP地址。

◎--rm:在停止运行(stop)后删除容器,这样在容器关闭后就不再需要用“docker rm”命令删除容器了。

◎ IMAGE:镜像的名字。

◎ COMMAND:需要启动的命令。

上面列出了“docker run”命令最常用的参数,其实它支持的参数还有很多,可以使用以下命令查看。

(2)通过以下命令可以查看正在运行的Docker容器。

此时,就能看到正在运行的容器的信息,注意可通过CONTAINER ID号操作指定的容器。

在搭建环境的最后一步中,用“docker run”命令启动一个容器,此时再开一个终端,然后用“docker ps”命令就可以看到这个容器的信息了。如果在容器内部运行“exit”命令,退出后再使用“docker ps”命令则看不到该容器。

(3)当执行“docker run”命令启动容器时,常使用-d参数使容器在后台运行,用“docker exec”命令可与正在运行的容器交互,如使用此命令进入Docker并安装一些软件。

该命令可进入正在运行的Docker容器,并启动容器中的“bash”。

(4)在容器内部与本地系统之间复制文件。在操作虚拟系统时,常常需要把数据拷入容器,运行之后再把运行结果从容器中拷到本地系统中。在不能上网的环境下,如果想在容器中安装软件,则需要将安装包复制到容器中。使用以下命令将本地文件复制到容器中:

使用以下命令将容器中的文件复制到本地:

(5)查看某一容器的log信息。

当容器在后台运行时,可能需要捕捉其输出信息。例如,当使用Docker在后台运行Jupyter(Python开发环境)时,需要获取其输出的token信息才能用网页登录。此时,就可以从log中查看该Docker的输出,具体命令如下。

(6)停止运行中的容器,命令如下。

(7)删除容器,命令如下。

删除之后,容器中的内容将不再保存。run命令包含建立(create)容器和启动(start)容器两步,相对应的关闭也分为stop(关闭)和rm(删除)两步。如果run命令在运行时不使用-rm参数,则停止运行后该容器不会被自动删除,需要用rm命令手动删除。

4.镜像的相关操作

如果把Docker看作虚拟机、容器看作虚拟机的运行实例,那么镜像(Image)则可看作存储在硬盘上的虚拟机对应文件。容器是动态的,镜像是静态的。当容器退出和删除后,镜像仍然存在,但需要注意的是在容器中对虚拟系统所做的修改并不会自动保存在镜像中。例如,本次操作在容器中安装了很多软件,退出后,当下次再运行该镜像时,这些软件是不存在的。

为什么Docker不像VirtualBox和VMware虚拟机一样,一边运行一边保存呢?这是因为很多时候在同一台机器上基于同一个镜像可能启动多个容器,如果即时保存,就无法确定镜像中保存的是哪一个容器中的内容。

镜像是容器的基础,一般通过管理镜像来管理容器,以及在不同机器之间传输或共享Docker虚拟系统。下面介绍有关镜像的基本操作。

(1)查看镜像。通过以下命令可查看当前可用的镜像,从返回的结果中可以看到之前下载的Ubuntu系统,其占用空间为88.9MB,主版本号REPOSITORY为ubuntu,子版本号为latest,可通过两个版本号的组合操作该镜像。

(2)以Build方法制作镜像。当需要保存安装的软件或数据以备下次使用时,就需要重新制作镜像。有两种制作镜像的方法:一种是用“docker build”命令创建新的镜像,另一种是用“docker commit”命令将某一容器中的修改保存成新的镜像。build方法通过当前目录下名为Dockerfile的文件指定基础镜像、安装包、环境变量等,并利用以下命令创建镜像,其中REPOSITORY是主版本号,TAG是子版本号。

(3)以修改方式制作镜像。build方法是创建镜像的标准方法,开发者可以从Dockerfile文件中清晰地看到新镜像与基础版本镜像的差异。但是当修改项目较多时,DockerFile文件的内容和逻辑可能非常复杂,这时就可以使用commit方法将某容器的内容制作成新镜像,具体方法如下:

其中,CONTAINER_ID是容器的ID号,可通过“docker ps”命令得到。在操作完成之后,使用“docker images”命令就可以看到新的镜像,并通过指定版本号启动不同镜像。新镜像只保存其基础版本的增补,并不会占用太大空间,这相对于虚拟机有明显的优势。在下次启动时,在run命令中指定新的版本号(REPOSITORY:TAG)即可用新的镜像启动容器。

另外,还可以通过TAG命令修改其版本号。

相对来说,build方法更加规范,能做出比较“干净”的镜像,而commit方法相对比较随意,常用于保存工作现场。

(4)删除镜像。在删除镜像前需要先停掉(stop)基于该镜像启动的容器,然后运行rmi命令。

(5)把镜像复制到另一台计算机上。在实际工作环境中,往往是在研发机上制作镜像,然后安装到生产环境中。因为Docker的镜像并不是存储在某一单个文件中,所以无法直接复制,需要从一台计算机上导出文件,然后复制到另一台计算机上,再执行导入操作。在需要导出的计算机A上执行以下命令:

将文件复制到需要导入的计算机B上,然后执行以下命令。

5.层

在导出Docker文件时,可以看到Docker文件占用的空间并不小,内容较多的Docker文件往往有几千兆,那么当频繁对Docker做修改并生成多个镜像文件时,是否会占用大量存储空间呢?答案是不会的。这是因为镜像是按层存储的,即在Docker内部只保存各个版本之间的差异。

层(Layer)是Docker用来管理镜像层的概念,因为单个镜像层可能被多个镜像使用,所以Docker把层(Layer)和镜像(Image)的概念分开,其中层(Layer)存放镜像层的diff_id,size,parent_id等内容。在同一个Docker版本管理系统中,只要层(Layer)一致,就只保存一份。

在默认情况下,镜像的存储路径为/var/lib/docker/aufs/,其中的Layers文件夹存储的就是镜像层的信息。

在计算机A上,镜像的存储是增量的,那么如果用save/load方式将镜像复制到另一台计算机B上,会不会占很大存储空间呢?答案是不会的。因为镜像的存储是按层堆叠的,同样的层只存储一次,所以在向另一台计算机导入镜像时,会对比和保存新镜像与现存层不同的部分,只是在复制过程中会占用较大空间。

如果想要查看当前Docker镜像与其基础版本及各分支的关系,就要先来看看元数据(metadata)。元数据就是关于层的额外信息,不仅包括Docker获取运行和构建时的信息,而且还包括父层的层次信息,只读层和读写层也都包含元数据。

用以下命令可获取容器或镜像的元数据:

此时,可以看到当前容器或镜像的信息,如镜像的ID和Parent,从而确定其继承关系。

通过对本小节的学习,读者可了解Docker的常用方法及基本原理,以便在后面学习了Python的Jupyter集成开发环境之后,能结合Docker和Jupyter创建包含Python开发环境的Docker镜像作为Docker的使用实践。