1.3 Python开发工具
Python的开发工具有很多,可繁可简,运行简单的Python脚本一般使用Linux的文本编辑器vim编写,使用命令行的“python”或“ipython”命令运行即可;相对复杂的功能一般都使用集成开发环境(Integration Development Environment,IDE)开发,以代码编辑界面为主、支持代码运行以及一些辅助工具。
常用的Python集成开发环境有Eclipse,Spyder,PyCharm,Eric,Jupyter Notebook等,其中Jupyter Notebook并不是最优秀的,但它可以使用浏览器在网络中的任意一台计算机上编写程序,这就使其在大数据开发中尤其是在集群环境下的开发中具有很大的优势。
1.3.1 Python命令行环境
1.在Docker环境下安装Python开发环境
在学习开发工具之前,先要安装Python开发环境。本小节介绍在Docker环境下安装Python基础环境,以及Jupyter的Python开发环境。首先,搜索可用的Python镜像。
此时会返回多个Python镜像文件,选择其中加星最多的名为“python”的镜像,将其下载到本地。
下载之后,通过“docker images”命令查看该镜像的基本信息。
可以看到,如果不指定子版本号,就会下载最终版本latest,该镜像大小为929MB。下一步进入该Docker查看系统信息,并使用“apt-get”命令安装Linux的文本编辑器vim。(apt-get是Ubuntu中的软件包管理工具)。
使用“pip”命令安装IPython(Interactive Python的简称,即交互式Python)。
此时,IPython被安装在容器中,当退出容器后,对容器的修改不会被保存。因此,需要用commit方法将容器的当前状态保存到镜像中,以备后续使用,可以先用“docker ps”命令查看CONTAINER_ID。
由结果可知,CONTAINER_ID为cde6197066b7,可用前几个字母代表,再用以下命令将其存储为新的镜像。镜像主版本号仍旧为python,子版本号为xy_190405,之后使用“docker images”命令即可查看该镜像。
此时,可看到新增的镜像文件。之后对Docker容器的修改如需保存都需要使用commit方法或者build方法生成新的镜像(简单起见,这里使用了commit方法)。
以上介绍了在Docker环境下安装Python开发环境,后续将会基于上述镜像运行书中的例程。读者也可以在Windows或者Linux虚拟机上直接安装Python环境,但直接安装相对依赖宿主机的软件环境,可能在运行本书后续的例程时需要考虑软件版本匹配的问题。
2.使用Python开发环境
在进入Docker内部环境之后,就可以正常使用Python和IPython了。在命令行中输入“python”即可进入交互式编程。
也可以用编辑器编写扩展名为“.py”的Python程序,并将文件名作为Python的命令参数,以运行程序中的代码,例如:
IPython是Python的扩展,除了提供Python的基本功能,还提供退出后保存历史、Tab自动补全、内嵌代码编辑、用英文“?”方式获取函数的帮助等功能。在命令行输入“ipython”命令即可进入交互式编程,即IPython Shell。IPython还提供浏览器图形界面IPython Notebook,这将在下一节介绍。
1.3.2 Jupyter环境
Jupyter Notebook原名为IPython Notebook,早期以支持Python为主,后来支持40多种编程语言。在大数据开发中,Jupyter是一款基于Web的开发工具,开发者可以在一台计算机上启动Jupyter的服务端,而在其他计算机上用浏览器通过指定端口开发程序,这是Jupyter的最大优势。这种方式可以让开发者利用集群中其他主机的运算资源,并且支持多人使用同一台计算机上的Jupyter编写程序。开发者可以使用集群中的任何一台计算机,只要支持普通浏览器(Firefox,Chrome及IE的较高版本)就能进行Python程序的开发和调试,尤其适用于当软件环境安装在网络的某台服务器上时,本地用任何一台计算机都可作为终端与之连接进行程序开发。
Jupyter还支持Markdown格式的文件,这可以让我们将带格式的文档、程序,以及程序运行结果保存在同一文件中。
Jupyter文件扩展名为ipynb,它是一种文本格式文件,可使用文件编辑器打开,其中包括Python源码及一些格式信息,可使用Jupyter将其转换成“.py”文件并导出执行。除了导出成Python默认的“.py”文件,Jupyter还支持将其导出成html,pdf等格式的文件,这使其在分享或示例代码时非常方便,完全不用考虑代码格式的问题。
“ipynb”格式的文件被广泛使用,如大数据比赛Kaggle的程序和说明大多数都是以这种格式编写的,Github也支持该格式的完美显示,即在Github中打开“.ipynb”文件看到的就是分块的代码。
下面介绍Jupyter的安装、使用,以及使用Docker启动Jupyter的方法。
1.在Docker环境下安装和运行Jupyter
由于Jupyter是C/S结构,因此需要服务端开放端口供客户端连接,Docker内部端口需要使用参数-p映射到其宿主机端口。另外,编写的程序也需要保存在Docker之外,以免在关闭容器时丢失数据。在Docker启动时,使用参数-v将宿主机目录映射到Docker内部,并用以下命令启动容器。
其中,$HOME指Linux下用户的主目录,先在其下建立src目录,然后将其映射到Docker的“/home/test/”目录下,并将Jupyter的默认8888端口映射到宿主机的8889端口;-it指以交互方式启动;python:xy_190405是上一步创建的新镜像的版本号。
在进入Docker之后,使用“pip”命令安装Jupyter,并启动Jupyter,然后将其网络地址全部设置为0,以便Docker外部可以通过宿主机的IP访问Jupyter。由于Docker内部用户为root,因此在启动时还需要设置参数--allow-root。
在返回结果中包含一个URL,其中token是其连接密码,此时Jupyter已经启动并通过Docker将其8888端口映射到宿主机的8889端口。在任何一台连接网络的计算机的浏览器中打开“http://宿主机IP:8889”,然后输入token密码即可连接Jupyter Notebook。如图1.6所示。
图1.6 Jupyter登录界面
至此,虽然Jupyter已经可以正常工作了,但是在每次启动时都需要输入token,另外在启动Jupyter时也需要进入Docker容器内部输入启动命令,比较麻烦。下面将介绍给Jupyter设置固定密码,以及将Jupyter启动成后台服务。
在Docker内部先查看当前用户的主目录:
然后生成Jupyter默认的配置文件:
并设置密码:
然后使用“echo”命令将Json文件中密码的哈希码添加到jupyter_notebook_config.py文件中,形如:
在输入以上命令时,使用Json文件中的password内容替换echo命令中的哈希码。其中,“echo”命令用于字符串输出,“>>”将输出重新定向到文件尾部。在另一终端使用“docker commit”命令对Docker的修改保存到镜像,如python:xy_190408,之后退出Docker,并使用以下命令设置在启动Docker时自动启动Jupyter。
在命令行中,将交互模式-it改为启动为后台服务-d并将“jupyter”命令及其参数加入命令行尾部,此时在使用浏览器访问Jupyter时即可使用新密码登录。如果想进入已启动的Docker容器,就可以使用“dockerexec”命令。首先用“docker ps”命令查看其CONTAINER_ID,然后指定该ID以交互方式连接已启动的Docker,并运行命令行工具bash。
2.Jupyter基本用法
登录后的Jupyter文件选择界面如图1.7所示。
图1.7 Jupyter文件选择界面
Jupyter首页显示的内容默认为是在启动Jupyter时当前目录中的内容。由于进入该Docker后默认进入根目录,因此在该路径下启动Jupyter时,界面中就会列出Docker中Linux根目录的结构。此时,在浏览器中可以编辑和运行已存在的程序,如果还没有Jupyter Notebook程序,则可单击右上角的“New”新建程序。在编写和调试程序的过程中,错误提示和运行结果也都会显示在浏览器中。
首先,从目录进入“/home/test”,之前在启动Docker时已将该目录映射到宿主机的$HOME/src目录下,以便容器关闭后程序不会丢失。然后,单击右上角的“New->Python 3”,新建一个程序(ipynb文件),程序界面如图1.8所示。
图1.8 Jupyter程序界面
图1.8中的File,Edit,View,Insert等都是Cell单元,它们是Notebook的基本元素,通过Insert菜单可添加新的单元。单元分为两种:Markdown单元(图1.8中的第一个单元)和代码单元(图1.8中的第二个单元)。
Markdown单元:一般用于编写注释和说明信息,包括文本格式、插入链接、图片、数学公式等数据。
代码单元:代码单元左边有“In []:”的序列标记,方便查看代码的执行次序。其运行结果显示在本单元下方。
单元有编辑模式和命令模式两种。编辑模式一般用于修改单元内容;命令模式用于对整个单元进行操作,如添加单元、删除单元等。比如,用“Shift+L”组合键控制是否显示行号,用“Shift+Enter”组合键执行当前单元中的代码。在命令模式下单元左侧显示蓝线,在编辑模式下左侧显示绿线,另外按Enter键可以切换到编辑模式,按Esc键可以切换到命令模式。
在Cell菜单中,可以选择运行全部代码,也可以选择运行某个代码单元,以Cell为单元运行程序类似于单步调试。代码分块是对代码的功能划分,有时也可以把完全不同的几种思路的程序写在同一个Notebook的不同Cell单元中,这样在调试过程中只需要运行不同单元即可,非常方便。
3.Jupyter魔法命令
除基本的Python代码外,Jupyter还支持魔法命令(Magic)。魔法命令包含两类:一类是以%开头的行魔法(Line magic),对单行起作用;另一类是以%%开头的单元魔法(Cell magic),对整个Cell起作用。下面介绍几个常用的魔法命令。
(1)查看系统支持的所有魔法命令。
(2)统计程序执行时间。
%timeit对单行语句执行多次,可用-n参数设置其运行次数、统计其平均执行时间。在上例中,程序被重复执行了100000次,最快3次的平均时长为9.32µs。
(3)查看当前Cell单元运行时间。
%timeit是运行多次,统计单行代码运行时间;%%timeit是运行多次,统计代码块运行时间。与timeit不同,time是统计单次运行时间。
(4)将Cell单元内容写入Python文件。
运行该单元后,在当前目录下生成test.py文件。(5)运行Python程序。
(6)将Matplotlib绘制的图片嵌入Jupyter Notebook中。
Matplotlib是最常用的Python图表绘图工具。在使用Jupyter调用其绘图函数时,其绘制的图片默认以弹出窗口方式显示。而在Docker下运行程序或在另一台计算机上运行程序时,往往不能正常弹出窗口,这时需要使用以下命令设置Matplotlib绘制的图表显示在浏览器中。
(7)查看当前变量。
(8)清除变量。
(9)加载文件内容。
运行后,test.py的内容被加载到当前代码块中,形如: