作者:京东科技隐衷计算产品部 孙晓军

1. Jupyter Notebook介绍

图1 Jupter我的项目整体架构

[https://docs.jupyter.org/en/l...]

Jupyter Notebook是一套基于web的交互式开发环境。用户能够在线开发和分享蕴含代码和输入的交互式文档,反对实时代码,数学方程,可视化和 markdown等。用处包含:数据清理和转换,数值模仿,统计建模,机器学习等等。

Jupyter Notebook外部通过内核保护状态并运行代码片段,浏览器显示代码片段和其执行的后果。Jupyter Notebook提供了一个用户交互式的开发环境,用户能够通过执行一部分代码片段,并察看执行后果。这种交互式设计,使得Jupyter Notebook非常适合数据迷信和机器学习的开发工作。

留神本文的代码和脚本,均基于Jupyter Notebook v6.5.2稳固版本。

2. Jupyter的工作形式

图2 Jupter Notebook工作形式

[https://docs.jupyter.org/en/l...]

Jupyter的次要工作单元是Jupyter Server和Kernel。其中Jupyter Server用来提供基于Web的界面和API服务,Kernel用来执行代码片段。浏览器通过Http和Websockets的形式和Jupyter Server进行交互,Jupyter Server和kernel之间,通过ZeroMQ进行数据通信。

Jupyter Server采纳经典的MVC模式,应用了tornado作为web服务器,用来提供地址映射和控制器逻辑,应用jinja2来提供模板视图性能。

Jupyter Notebook(v6.5.2)我的项目的次要模块构造如下:

模块阐明
notebookNotebook功能模块。
terminal终端模块。为Jupyter提供控制台交互能力。
view文件可视化模块。比方pdf文件的显示。
tree工作区目录树
nbconvert格局转换模块,能够把Jupyter Notebook转换成html,pdf等格局
kernelJupyter Notebook 内核
servicesJupyter Notebook REST API模块
i18nJupyter Notebook多语言资源

3. 装置Jupyter Notebook

前置条件

Python和pip

不同的Jupyter Notebook对Python有不同的版本要求。咱们装置的最新的稳固版本v6.5.2的Jupyter Notebook,要求Python的最低版本为3.6。留神这个Python的版本,不同于内核的Python版本。对于Jupyter内核来说,反对的Python版本和Jupyter Notebook依赖的Python版本没有关系。

在Linux零碎下装置Jupyter Notebook

应用pip装置Jupyter notebook非常简单。如果服务器同时领有Python2和Python3的pip,留神须要应用pip3来替换命令中的pip。

# 更新pippip install --upgrade pip# 装置jupyterpip install jupyter# 查看装置的jupyterjupyter --version//输入 notebook  : 6.5.2

4. 配置和启动Jupyter

Jupyter提供了大量的启动参数,用来配置Jupyter Server。咱们能够在启动Jupyter服务时,通过命令行参数的形式配置以后启动的服务,但更广泛的形式是应用Jupyter的配置文件。

# 生成配置文件jupyter notebook --generate-config// 默认生成的配置文件地位:/root/.jupyter/jupyter_notebook_config.py# 批改Jupyter配置文件...# 启动jupyterjupyter notebook

Jupyter间接应用一个Python文件来配置Jupyter服务,所有的配置项均通过Python代码来实现。罕用的配置项及其阐明如下:

名称默认值阐明
c.NotebookApp.allow_rootFalse为了平安,Jupyter默认不容许应用root用户启动。如果须要以root用户的身份启动Jupyter,须要开启此设定
c.NotebookApp.allow_origin''当须要Jupyter内嵌到iframe时,能够设置为“*“来防止跨origin的限度
c.NotebookApp.iplocalhost当须要通过外网地址来拜访Jupyter服务时,须要设置一个无效的服务器IP地址。
c.NotebookApp.port8888Jupyter server对外服务端口
c.NotebookApp.notebook_dir/Jupyter的工作空间,默认能够拜访服务器上以后用户的所有文件系统
c.NotebookApp.open_browserTrue启动服务后是否立刻通过浏览器关上服务地址
c.NotebookApp.default_url/treeJupyter服务的默认地址
c.NotebookApp.extra_static_paths[]扩大动态文件目录
c.NotebookApp.extra_template_paths[]扩大模板文件目录
c.KernelSpecManager.allowed_kernelspecsset()默认容许应用所有的kernel
c.NotebookApp.nbserver_extensions{}容许加载的Jupyter Server扩大

5. 应用Jupyter

5.1. 创立Notebook

启动Jupyter 后,在浏览器内输出 http://服务器地址:端口/,Jupyter会默认重定向到.default_url指定的工作区目录树地址,默认是工作区目录树的界面。

如果在拜访的过程中,应用了默认的token作为其认证形式,那么在首次关上时,须要输出Jupyter Notebook的token值,这个值能够在启动Jupyter时的控制台输入中找到,或者应用Jupyter命令来查问

# 查问运行的jupyter notebookjupyter notebook list//返回后果中蕴含了http://x.x.x.x:8899?token=ABC 的信息,其中的ABC就是咱们须要的token

图3 Jupter Notebook的默认工作区目录树页面

Jupyter Notebook通过Jupyter Server提供基于Web的平台无关的工作形式,这使得跨平台开发和合作,代码分享等能力变得比传统IDE更加容易。

在Jupyter 工作区治理界面,用户能够灵便地以相似文件系统的形式管理工作区的数据。能够创立文件和文件夹,编辑文件和文件夹,能够上传和下载文件。通过抉择一个Jupyter内核,能够创立一个Notebook文件。

图4 通过Jupyter内核创立一个Notebook

5.2. 应用Notebook

应用Python3内核创立一个Notebook后,咱们失去一个xxx.ipynb(IPython Notebook)文件。这个文件是一个json格局的文本文件,其中蕴含了咱们在Notebook中编写的代码和文本内容,也蕴含了界面上没有显示的元数据信息。通过在工作区目录界面抉择一个notebook文件,点击编辑,咱们能够查看到ipynb文件的原始内容。

图5 ipynb文件的原始内容

咱们能够像应用其它IDE相似的形式来应用Notebook,在应用Notebook上,咱们次要关注下Jupyter内核和单元格。

内核是执行单元格代码的外围过程,不同的内核,决定了咱们在单元格中可能编写哪些语言的代码,以及对应了指定的编程语言的哪个版本等信息。

单元格是整个Notebook的外围组成部分,咱们编写的代码和文本,通过一些列Notebook单元格来组成。Notebook提供了Code,Markdown, Raw NBConvert, Heading四种类型的单元格。

•Code单元格。用来编写内核指定语言的程序代码

•Markdown单元格。应用Markdown编辑器的语法来编辑富文本

•Raw NBConvert单元格。原始的文本,不会被当作代码或markdown被解释执行

•Heading单元格。Heading是Mardown的一个子集,对应了Markdown中的题目编写语法

Jupyter Notebook应用了机器学习中检查点的概念,在咱们批改Notebook的过程中,Jupyter会主动保留咱们的批改,咱们也能够通过【文件】->【保留】来手动保留检查点。检查点文件蕴含了咱们编写的Notebook内容,以及执行代码单元格之后的输入。咱们能够在工作空间的“.ipynb_checkpoints”文件夹下,找到这些检查点文件。

图6 应用Jupyter单元格来编写交互式代码

5.3. 分享Notebook

相较于应用传统的IDE编写的代码,基于Web服务的Jupyter Notebook在代码分享上领有着人造的劣势。

在Jupyter Notebook中,咱们能够通过两种不同的形式分享咱们创作的nootbook。

  1. 交互式Notebook文档

传统的技术文档或者说明书,通过动态的文本,配合图片和视频,来形容和解说特定的技术或性能。有了Jupyter Notebook后,咱们依然能够应用Notebook来编写相似传统的技术文档。在此基础上,咱们能够退出更活泼的代码交互单元格,用户通过查看文档阐明,并与文档中提供的代码进行互动,能够更活泼地介绍产品中的性能和技术。每个Jupyter Notebook的ipynb文件,都对应了一个独立的拜访地址: http://x.x.x.x:8899/notebooks... ,通过分享此文件的地址,其余用户能够不便地应用蕴含了富文本和可执行的代码的交互式Notebook文档。

  1. 离线Notebook文档

咱们通过逐渐执行文档中的所有单元格,失去一个蕴含了咱们编写的阐明和代码,以及代码执行的输入后果的残缺文档。之后点击【文件】-> 【另存为】,抉择一种适合的文件格式。咱们能够把文档导出为一份动态文件,通过共享此动态文件,咱们实现了Notebook文档的离线分享。

5.4. 魔法函数

Jupyter Notebook提供了一些列魔法函数来加强Jupyter Code单元格的性能,通过魔法函数,咱们可能执行javascript脚本,html代码,运行另一个可执行程序等许多额定的性能。

咱们能够在Jupyter代码单元格中应用 %lsmagic命令来查看所有的魔法函数,如果要浏览具体的魔法函数的应用阐明,能够参考: https://ipython.readthedocs.i...

魔法函数分为行魔法函数,单元格魔法函数和会话魔法函数。顾名思义,行魔法函数只对以后行起作用,而单元格魔法函数则作用于整个单元格,会话魔法函数则作用于整个会话期间。

一些罕用的魔法函数:

指令阐明
%matplotlib设置matplot绘图的显示模式
%%javascript单元格内的代码被辨认为javascript代码
%%html单元格内的代码被辨认为html代码
%run执行内部脚本文件
%pwd获取当前工作的目录地位(非工作空间目录地位)
%writefile以文件模式保留以后单元格代码
%timeit获取本行代码的执行工夫
%debug激活调试模式

6. 治理Jupyter

6.1. 多语言

Jupyter Notebook应用i18n目录下的资源来进行多语言翻译。在Jupyter Notebook启动时,会加载i18n目录下的多语言资源。之后依据http申请指定的语言,为响应数据提供对应的多语言翻译。如果没有对应的翻译,则保留原始的多语言标签值(英文)。如果调整了多语言翻译,须要重新启动Jupyter Notebook能力应用新的语言包。

Jupyter Notebook的翻译资源次要散布在三个po文件中:

•nbjs.po - js文件中的多语言数据

•nbui.po - UI界面中的多语言数据

•notebook.po - notebook中的多语言数据

原始的po文件,须要通过pybabel工具,把po文件编译成mo文件,之后部署在$notebook/i18n/${LANG}/LC_MESSAGES/目录下($notebook是notebook的装置目录),能力在Jupyter Notebook中作为多语言的资源包来应用。

# 应用pybabel编译多语言po文件pybabel compile -D notebook -f -l ${LANG} -i ${LANG}/LC_MESSAGES/notebook.po -o ${LANG}/LC_MESSAGES/notebook.mopybabel compile -D nbui -f -l ${LANG} -i ${LANG}/LC_MESSAGES/nbui.po -o ${LANG}/LC_MESSAGES/nbui.mopybabel compile -D nbjs -f -l ${LANG} -i ${LANG}/LC_MESSAGES/nbjs.po -o ${LANG}/LC_MESSAGES/nbjs.mo

图7 应用了中文语言包后的中文Notebook界面

6.2. 内核治理

内核(kernel)是独立于jupyter服务和界面之外的用来运行Jupyter代码单元格的过程,Jupyter默认提供了ipykernel内核来反对Python开发语言。Jupyter社区提供了jupyterC, IJava,xeus-cling, xeus-sql等泛滥其它编程语言的内核,用来反对C/C++, Java, SQL等编程语言。

ipykernel默认应用零碎环境下的Python来提供服务。咱们能够应用ipykernel装置多个Python kernel来提供Python2.x, Python3.x等多个Python内核环境。

装置kernel后,kernel的信息被保留在kernel.json文件中,咱们能够在 /usr/local/share/jupyter/kernels 目录,找到Jupyter装置的所有kernel以及对应的kernel.json文件。

kernel能够间接继承自装置kernel的Python指令,也能够应用Python虚拟环境。

# 1.间接继承自Python指令的kernel装置# 装置ipykernelpip install ipykernel# 装置kernelpython -m ipykernel install --name tensorflow2 --display-name "tensorflow2"# 2. 在Python虚拟环境下的kernel装置# 激活虚拟环境source activate myenv# 装置ipykernelpip install ipykernel# 装置kernelpython -m ipykernel install --name myenv --display-name "Python3 (myenv)"

如果须要查看以后的kernel列表,以及删除曾经装置的kernel,能够应用如下的Jupyter命令:

# 查看曾经装置的kernel列表jupyter kernelspec list# 删除列表中指定的kerneljupyter kernelspec remove kernelname

6.3. REST API

Jupyter提供了REST API接口来和Jupyter server进行交互。借助REST API的能力,咱们能够以编程的形式和Jupyter Server进行交互,灵便地治理Jupyter Server。另外REST API为现代化的软件开发提供了一个优良的能力:自动化。

借助Jupyter Notebook REST API,能够实现文件的上传和下载,检查点治理,会话治理,内核治理,终端治理等一些列治理能力。残缺的Jupyter REST API接口列表能够参考: https://jupyter-server.readth...

要应用REST API,须要在申请中携带认证信息。Jupyter反对间接把token作为query string的形式来认证,也能够应用规范的Http Authorization头信息来实现认证。应用Authorization头来认证的格局如下:

Authrozation: token 527a9f1430ccfed995ebcf15517583a2547c2469bc3c47a6

图8 应用Postman来调用Jupyter REST API接口

6.4. 平安治理与多人合作

Jupyter提供了灵便弱小的能力,用以反对在线的交互式文档和代码的编写。但Jupyter我的项目本身没有提供精细化的平安管理体系,用以反对多用户下灵便地应用Jupyter Notebook的性能。对于文件平安,Jupyter依赖于启动服务的linux用户,正当地配置启动Jupyter的用户的权限,能力保障应用Jupyter的用户,不会对系统或我的项目造成毁坏。Jupyter工作空间的设定,仅起到了不便Jupyter使用者治理必要文件的易用性,不能阻挡用户拜访和管理工作空间外的文件系统。另外,配合应用Python虚拟环境,能够避免Jupyter Notebook提供的 pip install ,pip uninstall性能,对现有我的项目环境造成毁坏。

在多人合作方面,JupyterHub我的项目提供了多人合作Jupyter Notebook和Jupyter lab开发的能力。应用JupyterHub,不同职能的用户能够在本人独立的空间内进行Notebook的编写工作,不同用户间也能够不便地分享各自的Notebook。

7. 扩大Jupyter

7.1. 前端扩大

Jupyter Notebook前端扩大(front end extension)是应用Javascript语言编写的异步模块,能够用来绘制Jupyter界面的仪表盘,Notebook,工具栏等,。定义一个前端扩大必须要实现一个load_ipython_extension办法,以后端控件被加载时,Jupyter client会调用load_ipython_extension办法。

Jupyter Notebook前端扩大能力目前还不是一个稳固的版本,不保障代码可能向后兼容。Jupyter的JS API目前也没有官网的文档,须要通过源代码或者理论加载的JS来查看Jupyter前端脚本的成员和办法。

咱们实现一个简略的前端扩大脚本,在jupyter前端的工具条中,增加一个自定义工具,当点击自定义工具时,弹出提示信息。

define([    'base/js/namespace'], function(    Jupyter) {    function load_ipython_extension() {        var handler = function () {            alert('欢送应用前端扩大!');        };        var action = {            icon: 'fa-comment-o',            help    : '前端扩大',            help_index : 'zz',            handler : handler        };        var prefix = 'my_extension';        var action_name = 'show-alert';        var full_action_name = Jupyter.actions.register(action, action_name, prefix); // returns 'my_extension:show-alert'        Jupyter.toolbar.add_buttons_group([full_action_name]);    }    return {        load_ipython_extension: load_ipython_extension    };});

完前端扩大代码后,咱们把脚本保留到main.js文件,搁置在/opt/my_extension目录下。接下来咱们应用jupyter nbextension工具来装置和启用前端扩大

# 装置前端扩大jupyter nbextension install /opt/my_extension# 启用前端扩大jupyter nbextension enable my_extension/main# 禁用前端扩大jupyter nbextension disable my_extension/main# 查看前端扩大列表jupyter nbextension list# 卸载前端扩大jupyter nbextension uninstall my_extension

图9 在Notebook工具条中退出的前端扩大

7.2. 服务端扩大

Jupyter服务端扩大(server extension)是应用Python语言编写的模块,能够用来解决发送到Jupyter Server的Http申请。应用Jupyter服务端扩大,能够更改现有Jupyter申请的数据和行为,也能够为jupyter Server定义新的服务处理程序。

定义一个服务端扩大模块要实现一个load_jupyter_server_extension办法,其中蕴含一个类型为notebook.notebookapp.NotebookApp的参数serverapp,serverapp的具体属性和办法能够通过Jupyter Notebook源代码中的notebookapp.py文件来查看。当服务端扩大被加载时,Jupyter Server会调用load_jupyter_server_extension办法。在load_jupyter_server_extension办法中,咱们能够通过调用serverapp的web_app属性的add_handlers办法来注册处理程序,用来解决特定的服务端申请。处理程序类须要继承自Jupyter的IPythonHandler类。在处理程序的办法中,能够应用Jupyter提供的@web.authenticated装璜器来为办法减少身份认证爱护。

通过服务端扩大,还能够与前端扩大联动,实现一个功能丰富的Jupyter Notebook前端控件。

# 定义一个处理程序from tornado import (    gen, web,)from notebook.base.handlers import IPythonHandlerclass HelloWorldHandler(IPythonHandler):    @web.authenticated    @gen.coroutine    def get(self):        self.finish(f'Hello, world!')# 实现load_jupyter_server_extension办法并注册处理程序def load_jupyter_server_extension(serverapp):    handlers = [        ('/myextension/hello', HelloWorldHandler)    ]    serverapp.web_app.add_handlers('.*$', handlers)

实现服务端扩大代码后,咱们把代码保留为__init__.py文件,要在Jupyter Notebook中应用处理程序,咱们还须要进行服务端扩大的装置和启用。不同于前端扩大,服务端扩大不能间接应用指令来装置,须要咱们手动编写安装程序。此外,Jupyter提供了主动启用服务端扩大和前端扩大的办法,须要咱们在脚本的根目录提供启用扩大的配置文件。

jupyter-config/├── jupyter_notebook_config.d/│   └── my_server_extension.json└── nbconfig/    └── notebook.d/        └── my_front_extension.json setup.py

退出了主动启用扩大的配置,咱们的服务端扩大目录构造如下:

hello-extension/├── __init__.pyjupyter-config/├── jupyter_notebook_config.d/    └── hello_extension.json

hello_extension.json文件的内容为:

{    "ServerApp": {        "jpserver_extensions": {            "hello_extension": true        }    }}

接下来咱们通过安装程序,装置服务端扩大的信息保留在/root/.jupyter/jupyter_notebook_config.json文件中。在装置实现后,咱们能够通过jupyter serverextesion工具来股那里服务端扩大

# 启用服务端扩大jupyter serverextension enable hello_extension# 禁用服务端扩大jupyter serverextension disable hello_extension# 服务端扩大间接卸载的办法,须要咱们通过pip uninstall 卸载安装程序,# 再通过手工批改/root/.jupyter/jupyter_notebook_config.json文件删除扩大信息来实现卸载

图10 在浏览器中测试装置的服务端扩大程序

7.3. 界面定制

Jupyter没有提供规范的界面定制的能力,但咱们能够手工调整jupyter生成的模板视图文件和款式文件,达到整条调整jupyter notebook的界面的能力。

Jupyter Notebook模板文件的地位为:$notebook/templates,款式和脚本定制举荐的计划是应用~/.jupyter/custom/custom.css和~/.jupyter/custom/custom.js文件。咱们能够间接在此基础上对文件进行批改,还能够通过extra_template_paths和extra_static_paths来引入其它地位的模板和其它动态文件。

图11 通过间接调整模板文件退出的界面定制按钮

7.4. 小部件

小部件(Widgets)是Jupyter交互式可视化数据出现部件。Jupyter Widgets同时蕴含了拜访后端数据和前端出现的能力,能够用于在Jupyter Notebook上活泼地展现服务端的数据和数据变动。

在v6.5.2稳固版本上,咱们目前只能应用零碎提供的小部件,还不能开发自定义小部件。在Jupyter notebook7.x版本中,开始提供了小部件的自定义开发能力。

# 确保装置了ipywidgets和traitletspip install --upgrade traitletspip install --upgrade ipywidgets# 装置和启用小部件jupyter nbextension install --py widgetsnbextensionjupyter nbextension enable --py widgetsnbextension

在装置和启用了小部件后,咱们能够在notebook中间接应用零碎提供的小部件。

图12 在Notebook中应用小部件

残缺的小部件列表和应用形式能够参考: https://ipywidgets.readthedoc...

8. 总结

Jupyter Notebook以其丰盛的性能,简略易用,弱小的交互能力和扩大能力,成为数据迷信和机器学习开发中的神器。目前,Jupyter Notebook反对超过40种编程语言,被利用于Google Colab, Kubeflow, 华为云,kaggle等多个出名我的项目中,大量机器学习和数据迷信的论文中应用到了Jupyter。Jupyter在数据可视化,晋升工作效率,改善用户体验和丰盛文档性能方面浮现了微小的威力。除此之外,Jupyter还提供的灵便弱小的扩大能力,更是为Jupyter的深层次应用提供了更广大的设想空间。如果你还没有开始接触Jupyter,那么就从当初开始吧。