应用Jupyter Notebooks(应用Jupytext和Papermill)主动生成报告
本文源码下载:笔记本来形容特定年份的世界人口和国内生产总值。应用简略:只需year在第一个单元格中更改变量,而后从新运行,即可取得所选年份的图表。但这须要手动干涉。如果能够主动执行更新并为每个可能的year参数值生成报告,将会更加不便(更一般而言,笔记本计算机不仅能够基于一些用户提供的参数,而且还能够通过与参数的连贯来更新其后果。数据库等)。
版本控制
在业余环境中,笔记本电脑是由数据科学家设计的,然而在生产环境中运行笔记本电脑的工作可能会由其余团队来解决。因而,一般而言,人们必须共享笔记本。最好通过版本控制系统来实现。
Jupyter笔记本因其版本控制的难度而闻名。让咱们思考下面的笔记本,文件大小为3 MB,其中大部分由嵌入式Plotly库奉献。如果咱们删除第二个代码单元的输入,笔记本将小于80 KB。删除所有输入后,大小仅为1.75 KB。这表明它的多少内容与纯代码无关!如果咱们不留神的话,笔记本中的代码更改将失落大量的二进制内容。
为了取得有意义的差别,咱们应用Jupytext(免责申明:我是Jupytext的作者)。Jupytext能够应用pip或装置conda。重新启动笔记本服务器后,Jupyter中将呈现一个Jupytext菜单:
咱们单击将笔记本与Markdown配对,保留笔记本...,而后取得笔记本的两种示意模式:(world_fact.ipynb 具备输出和输入单元格)和 world_fact.md(仅具备输出单元格)。
Jupytext将笔记本示意为Markdown文件与所有次要的Markdown编辑器和查看器兼容,包含GitHub和VS Code。Markdown版本例如由GitHub出现为:
如您所见,Markdown文件不蕴含任何输入。实际上,因为咱们只须要共享笔记本代码,因而咱们不心愿在此阶段应用它。Markdown文件还具备十分清晰的差别历史记录,这使笔记本的版本控制变得简略。
该world_facts.md文件由Jupyter当您保留在笔记本自动更新。反之亦然!如果world_facts.md应用文本编辑器进行批改,或者通过从版本控制系统中提取最新的内容进行批改,则在浏览器中刷新笔记本时,更改将显示在Jupyter中。
在咱们的版本控制系统中,咱们只须要跟踪Markdown文件(甚至能够显式疏忽所有.ipynb文件)。显然,执行笔记本的团队须要从新生成world_fact.ipynb文档。为此,他们在命令行中应用Jupytext:
$ jupytext world_facts.md --to ipynb[jupytext] Reading world_facts.md[jupytext] Writing world_facts.ipynb
当初,咱们正在正确地对笔记本进行版本控制。差别历史更加清晰。例如,查看咱们的报告中减少的国内生产总值的样子:
Jupyter笔记本作为脚本?
作为Markdown示意的代替办法,咱们能够 world_facts.py 应用Jupytext将笔记本与脚本配对。如果您的笔记本中蕴含的代码多于文本,则应尝试一下。这通常是迈向残缺而高效的长笔记本重构的第一步,一旦笔记本被示意为脚本,您就能够提取任何简单的代码,并应用IDE中的重构工具将其移至(通过单元测试的)库中。
JupyterLab,JupyterHub,Binder,Nteract,Colab和Cloud笔记本?
您是否应用JupyterLab而不是Jupyter Notebook?不必放心:以上办法在这种状况下也实用。您只须要为JupyterLab应用Jupytext扩展名,而不是应用Jupytext菜单。如果您想晓得,Jupytext也能够在JupyterHub和Binder中应用。
如果您应用其余笔记本编辑器,例如Nteract桌面,CoCalc,Google Colab或其余云笔记本编辑器,则可能无奈应用Jupytext作为编辑器中的插件。在这种状况下,您只需在命令行中应用Jupytext。闭上你的笔记本电脑和注入的配对信息到world_facts.ipynb 与
$ jupytext --set-formats ipynb,md world_facts.ipynb
而后放弃两个示意与
$ jupytext --sync world_facts.ipynb
笔记本参数
Papermill是用于执行带参数笔记本的参考库。
造纸厂须要晓得哪个单元格蕴含笔记本参数。只需parameter应用Jupyter Notebook中的单元格工具栏在该单元格中增加标签即可实现此操作:
在JupyterLab中,您能够应用celltags扩展名。
并且,如果您违心,也能够间接world_facts.md在此处编辑并增加标签:
year = 2000
主动执行
当初,咱们领有在生产服务器上执行笔记本所需的所有信息。
生产环境
为了执行笔记本,咱们须要晓得它应该在哪个环境中运行。在此示例中,当咱们应用Python笔记本工作时,咱们将其依赖关系列在requirements.txt文件中,这是Python我的项目的规范。
为简略起见,咱们还将笔记本工具蕴含在同一环境中,即增加jupytext和增加papermill到同一requirements.txt文件中。严格来说,这些工具能够在另一个Python环境中装置和执行。
应用以下任一办法创立相应的Python环境
$ conda create -n run_notebook --file requirements.txt -y
或者
$ pip install -r requirements.txt
(如果在虚拟环境中)。
请留神,该requirements.txt文件只是指定执行环境的一种形式。该重复性执行环境标准的粘结剂队伍为主题的最残缺的参考资料之一。
继续集成
低劣作法是测试对笔记本计算机或其要求的每个新奉献。为此,您能够应用例如Travis CI(间断集成解决方案)。您仅须要以下两个命令:
pip install -r requirements.txt
装置依赖项jupytext world_facts.md --set-kernel - --execute
在以后的Python环境中测试笔记本的执行状况。
您能够在咱们的.travis.yml
文件中找到一个具体示例。
咱们曾经在主动执行笔记本了,不是吗?Travis会通知咱们是否在我的项目中引入了回归…停顿如何!然而咱们还没有100%实现,因为咱们承诺要应用参数执行笔记本。
应用正确的内核
Jupyter笔记本与内核(即,指向本地Python环境的指针)相关联,然而该内核可能在您的生产计算机上不可用。在这种状况下,咱们只需更新笔记本内核,以指向咱们刚刚创立的环境:
$ jupytext world_facts.ipynb --set-kernel-
请留神,--set-kernel -
下面的减号示意以后的Python环境。在咱们的示例中,得出:
[jupytext] Reading world_facts.ipynb[jupytext] Updating notebook metadata with '{"kernelspec": {"name": "python3", "language": "python", "display_name": "Python 3"}}' [jupytext] Writing world_facts.ipynb (destination file replaced)
如果您要应用另一个内核,只需将内核名称传递给该--set-kernel选项(您能够应用来获取所有可用内核的列表,jupyter kernelspec list
和/或应用来申明一个新内核python -m ipykernel install --name kernel_name --user
)。
用参数执行笔记本
当初,咱们能够应用Papermill执行笔记本了。
$ papermill world_facts.ipynb world_facts_2017.ipynb -p year 2017Input Notebook: world_facts.ipynb Output Notebook: world_facts_2017.ipynb 100%|██████████████████████████████████████████████████████| 8/8 [00:04<00:00, 1.41it/s]
功败垂成!笔记本已执行,文件world_facts_2017.ipynb
蕴含输入。
公布笔记本
当初该交付刚刚执行过的笔记本了。兴许您想在邮箱中找到它?或者,兴许您心愿取得一个能够查看后果的URL?咱们介绍了几种办法。
GitHub能够显示Jupyter笔记本。这是一个不便的解决方案,因为您能够轻松抉择谁能够拜访存储库。只有您在笔记本中不蕴含任何交互式JavaScript图或小部件,此办法就能够很好地工作(GitHub疏忽JavaScript局部)。就咱们的笔记本而言,交互式绘图未呈现在GitHub上,因而咱们须要另一种办法。
另一个抉择是应用Jupyter Notebook Viewer。该nbviewer服务能够使任何笔记本电脑是在GitHub上公开。因而,咱们的笔记本在此处正确渲染。如果您的笔记本不是公开的,则能够抉择在本地装置nbviewer。
或者,您能够将执行的笔记本转换为HTML,并将其公布在GitHub页面上,或在您本人的HTML服务器上,或通过电子邮件发送。轻松将笔记本转换为HTML
$ jupyter nbconvert world_facts_2017.ipynb --to html[NbConvertApp] Converting notebook world_facts_2017.ipynb to html [NbConvertApp] Writing 3361863 bytes to world_facts_2017.html
生成的HTML文件包含以下代码单元:
然而,兴许您不想看到HTML中的输出单元格?您只须要增加--no-input:
$ jupyter nbconvert --to html --no-input world_facts_2017.ipynb --output world_facts_2017_report.html
您会失去一份更清晰的报告:
将独立的HTML文件作为附件发送到电子邮件中很容易。也能够将报告嵌入到电子邮件注释中(但交互式绘图无奈应用)。
最初,如果您正在寻找一份欠缺的报告并且对LaTeX有所理解,则能够尝试Jupyter的nbconvert命令的PDF导出选项。
应用管道
应用命名文件的代替办法是应用管道。jupytext,nbconvert并且papermill所有人都反对它们。以前的命令的单行代替是:
$ cat world_facts.md \ | jupytext --from md --to ipynb --set-kernel - \ | papermill -p year 2017 \ | jupyter nbconvert --stdin --output world_facts_2017_report.html
论断
当初,您应该可能基于Jupyter笔记本电脑建设用于在生产中生成报告的残缺管道。咱们曾经看到了如何:
- 应用Jupytext版本控制笔记本
- 在多个用户之间共享笔记本及其依赖项
- 继续集成测试笔记本
- 应用Papermill执行带有参数的笔记本
- 最初,如何公布笔记本(在GitHub或nbviewer上),或将其出现为动态HTML页面。
本示例中应用的技术齐全基于Jupyter Project,它是数据迷信的事实上的规范。这里应用的工具都是开源的,并且能够与任何继续集成框架一起很好地工作。
您领有打算和交付通过微调的,无代码的报告所需的所有!
结语
这里应用的工具是用Python编写的。然而它们与语言无关。感激Jupyter框架,它们实际上实用于存在Jupyter内核的40多种编程语言中的任何一种。
当初,假如您曾经编写了一个蕴含一些Bash命令行的文档,就像这篇博客文章一样。装置Jupytext和bash内核,博客文章将成为此交互式Jupyter笔记本!
更进一步,咱们是否应该确保帖子中的每条指令都切实有效?咱们通过继续的集成来做到这一点……扰流板警报:就像jupytext --execute README.md!一样简略!
致谢
Marc感激Eric Lebigot和Florent Zara对本文的奉献,并感激CFM通过其开源打算反对这项工作。
对于作者
本文由Marc Wouts撰写。Marc于2012年退出CFM的钻研团队,从事过从最佳交易到投资组合构建的一系列钻研我的项目。
Marc始终对寻找无效的工作流以进行波及数据和代码的合作钻研感兴趣。在2015年,他编写了一个外部工具,用于在Atlassian的Confluence Wiki上公布Jupyter和R Markdown笔记本,为在笔记本上进行合作提供了第一个解决方案。在2018年,他编写了Jupytext这个开源程序,该程序可简化Jupyter笔记本的版本控制。Marc也对数据可视化感兴趣,并在CFM协调无关此主题的工作组。
Marc于2007年取得巴黎狄德罗大学的概率论博士学位。
免责申明
本文档中蕴含的所有观点均形成其作者的判断,并不一定反映资本基金治理公司或其任何分支机构的观点。本文档中提供的信息仅是个别信息,不形成投资或其余倡议,如有更改,恕不另行通知。以上成绩源自Google翻译。微信 yujiabuao.