使用Jinja2的Jupyter Notebook的自定义模板

本文概述

  • 什么是模板?
  • 神社简介
  • 了解带有模板的基本渲染
  • 模板继承
  • 使用nbconvert导出Jupyter Notebook
  • 总结
在数据科学中, 你通常需要创建工作报告以显示给决策者或其他非技术人员。将Jupyter Notebook转换成稳定的PDF或HTML文档, 对于没有安装Python或Jupyter的同事来说更容易。 Python使用名为nbconvert的库和名为Jinja2的模板语言来转换文档。模板定义如何将文档显示在网页或其他输出格式上。了解如何自定义模板有助于制作出精美的笔记本报告。
Jupyter Notebook是在浏览器中运行Python代码的一种方式。如果你想了解有关Python的更多信息, 请务必查看我们的免费的Python数据科学入门课程。
在本教程中, 你将涵盖以下主题:
  • 模板和Jinja2模板设计器。
  • 渲染模板和继承。
  • 如何使用nbconvert导出笔记本。
  • 用于扩展Jupyter默认模板以进行HTML导出的语法和结构。
  • 导出为LaTeX和PDF格式的区别。
什么是模板? 在Python Wiki中:” 模板化, 尤其是Web模板化, 是一种以不同形式表示数据的方式……模板化解决方案经常涉及文档(模板)和数据。模板通常看起来像最终输出, 带有占位符, 而不是实际数据”
通过使用文件-> 下载为(可以在Jupyter实验室中看到导出为笔记本), 可以轻松地导出Jupyter Notebook。该选项使用Jupyter主环境中保存的默认模板。 Jinja2是Python强大的模板语言, 用于定义阻止和排版。模板具有由标签定义的部分, 这些部分告诉模板如何呈现输入数据。呈现模板时, 数据将替换变量或表达式。
模板不同部分的分隔符为:
  • {%… %}的报表
  • {{… }}用于表达式打印到模板输出
  • {#… #}表示注释未包含在模板输出中
看一下这个简短的Jinja模板示例(由Jinja2文档提供):
< !DOCTYPE html> < html lang="en"> < head> {% block head %} < link rel="stylesheet" href="http://www.srcmini.com/style.css" /> < title> {% block title %}{% endblock %} - My Webpage < /title> {% endblock %} < /head> < body> < div id="content"> {% block content %}{% endblock %}< /div> < div id="footer"> {% block footer %} & copy; Copyright 2008 by < a href="http://domain.invalid/"> you < /a> . {% endblock %} < /div> < /body> < /html>

你可以在上面看到, 大多数模板类似于普通的HTML文档。 Jinja需要一些额外的行来将代码解释为模板。 {%block head%}定义HTML文档的head部分, 以及此模板将如何扩展其格式。 {%块标题%}部分描述了输入标题的显示位置。 {%endblock%}会出现在多个位置, 因为这会结束任何相应的模板块。
现在, 你准备好学习如何使用Jinja创建自己的自定义模板!
神社简介 Jinja是一个模板引擎, 可让你定义文档的显示方式。具体来说, 对于本教程, 你将重点介绍如何在Jinja模板的帮助下导出Jupyter Notebook。
首先, 从Jinja2导入模板:
from jinja2 import Template

了解带有模板的基本渲染 在Jinja模板中渲染数据非常简单。使用方括号和变量名, 可以在模板中显示数据:
myTemplate = Template("My template is {{ something }}!") myTemplate.render(something="awesome")

'My template is awesome!'

调用.render(input)可以使你的笔记本中显示模板, 而输入内容将替换模板中的通用{{something}}。这是Jinja中的表达式用法示例。
你可以通过定义Jinja会解释的Python语句来更动态地使用模板。
myFancyTemplate = Template("Let's count to 10: {% for i in range(11) %}{{i}} " "{% endfor %}") myFancyTemplate.render()

"Let's count to 10: 0 1 2 3 4 5 6 7 8 9 10 "

注意, 你定义了一个for循环, 并且模板以0到10之间的数字呈现数字。 {%expression%}的语句语法为创建自定义模板提供了很大的灵活性。
模板继承 为了制作扩展默认Jupyter导出的模板, 你可以使用模板继承。继承是编程中的概念, 你可以在子对象中实现一些可以利用父级定义的功能的对象。一个简单的示例是, 如果你有一个可以吠叫, 吃饭和散步的Dog对象, 则可以使用继承来创建Dalmatian对象, 该对象可以继承所有这些属性并添加其他属性, 例如有斑点。在本教程中, 你将看到继承对于模板化非常有用, 因为通常只需要进行很小的更改即可自定义输出。像其他继承语言一样, Jinja使用extend和super之类的关键字来访问父级定义。
看一看上面的示例父模板, 名为base.html:
< !DOCTYPE html> < html lang="en"> < head> {% block head %} < link rel="stylesheet" href="http://www.srcmini.com/style.css" /> < title> {% block title %}{% endblock %} - My Webpage < /title> {% endblock %} < /head> < body> < div id="content"> {% block content %}{% endblock %}< /div> < div id="footer"> {% block footer %} & copy; Copyright 2008 by < a href="http://domain.invalid/"> you < /a> . {% endblock %} < /div> < /body> < /html>

子模板可能看起来像这样(由Jinja2文档提供):
{% extends "base.html" %}{% block title %}Index{% endblock %}{% block head %} {{ super() }} < style type="text/css"> .important { color: #336699; } < /style> {% endblock %}{% block content %} < h1> Index< /h1> < p class="important"> Welcome to my awesome homepage. < /p> {% endblock %}

请注意, 子模板如何以{%扩展” base.html” %}开头。该声明告诉Jinja模板引擎如何处理此文档(作为具有base.html继承的HTML)。使用此子模板可以为首页指定不同的属性(例如特定的CSS颜色)。同样, 你可以在head块中看到子模板通过调用super()继承了父模板的样式。
使用nbconvert导出Jupyter Notebook 现在, 你了解了模板的基本语法和继承, 你可以学习如何使用nbconvert导出Jupter Notebook并定义模板以自定义输出。
首先导入nbconvert:
import nbconvert

nbconvert可以创建多种格式的输出。本教程将重点介绍HTML和LaTeX / PDF输出。要在笔记本中查看输出, 请在调用nbconvert时使用IPython显示功能和– stdout。
example = !jupyter nbconvert --to html 'Example.ipynb' --stdout from IPython.display import HTML, display display(HTML('\n'.join(example)))

[NbConvertApp]将笔记本Example.ipynb转换为html
使用Jinja2的Jupyter Notebook的自定义模板

文章图片
笔记本的此代码段看起来与原始.ipynb文件非常相似。输出显示为独立的文档, 带有标题和文本, 通常在笔记本中显示。代码单元块显示为灰色框(称为” 笔记本样式” )。你可以看到的主要区别是Jupyter默认的HTML模板不像活动的Notebook那样显示” Out:” 提示。
使用nbconvert和自定义子模板导出Jupyter Notebook
通常, 你需要扩展Jupyter Notebook的默认导出模板, 并对输出进行较小的设计更改。
例如, 看下面这个简单的模板, 该模板从输出中删除Markdown单元(称为rmMkdwn.tpl):
{% extends 'basic.tpl'%}{% block markdowncell -%} {% endblock markdowncell %}

通过– template =选项将模板应用于nbconvert:
example = !jupyter nbconvert --to html 'Example.ipynb' --template='rmMkdwn.tpl' --stdout display(HTML('\n'.join(example)))

[NbConvertApp]将笔记本Example.ipynb转换为html
使用Jinja2的Jupyter Notebook的自定义模板

文章图片
即使是一个非常简单的模板, 例如rmMkdwn.tpl, 也可以极大地帮助你自定义输出。
看一下这个更复杂的模板, 该模板将单元格用红色框起来(称为boxRed.tpl):
{% extends 'full.tpl'%}{% block any_cell %} < div style="border:thin solid red"> {{ super() }} < /div> {% endblock any_cell %}

example = !jupyter nbconvert --to html 'Example.ipynb' --template='boxRed.tpl' --stdout display(HTML('\n'.join(example)))

[NbConvertApp]将笔记本Example.ipynb转换为html
使用Jinja2的Jupyter Notebook的自定义模板

文章图片
在上方, 你可以看到唯一的样式更改是每个单元格周围的红色框。 super()用于确保每个单元格都保持其父模板full.tpl中的样式。
导出到LaTeX和PDF模板的差异
由于{}和%在LaTeX中是特殊字符, 因此必须使用(())和*。同样, 默认的LaTeX模板是base.tplx, article.tplx和report.tplx, 它们对应于LaTeX文档类。
看一下使用LaTeX子模板删除Markdown单元格:
((* extends 'article.tplx' *))((* block markdowncell -*)) ((* endblock markdowncell *))

nbconvert可以生成LaTeX或PDF输出-从LaTeX模板编译PDF输出。为了便于阅读, 请查看使用rmMkdwn.tplx导出为PDF时发生的情况。
!jupyter nbconvert --to pdf 'Example.ipynb' --template='rmMkdwn.tplx' from IPython.display import IFrame IFrame('Example.pdf', width=800, height=500)

[NbConvertApp] Converting notebook Example.ipynb to pdf [NbConvertApp] Support files will be in Example_files/ [NbConvertApp] Making directory Example_files [NbConvertApp] Writing 16047 bytes to notebook.tex [NbConvertApp] Building PDF [NbConvertApp] Running xelatex 3 times: ['xelatex', 'notebook.tex'] [NbConvertApp] Running bibtex 1 time: ['bibtex', 'notebook'] [NbConvertApp] WARNING | bibtex had problems, most likely because there were no citations [NbConvertApp] PDF successfully created [NbConvertApp] Writing 16102 bytes to Example.pdf

使用Jinja2的Jupyter Notebook的自定义模板

文章图片
注意, 此输出结果与HTML版本截然不同。 LaTeX将第一个Markdown单元提供给文章标题, 因此它仍显示在输出中。模板确实正确删除了字幕(因此将Markdown单元视为真正的Markdown)。文章文档类将以今天的日期进行更新-这不是原始笔记本中的日期。字体和间距与HTML版本不同。最后, 默认情况下, 输出使用经典的IPython显示, 而不是” 笔记本样式” 显示。
如果你选择扩展Jupyter中的LaTeX文档类, 请确保你了解它将使用的格式。
总结 关于模板, Jinja2和nbconvert有一些重要的事情要记住。
模板定义如何将文档显示在网页或其他输出格式上。 Jupyter Notebook实现了Jinja模板以显示不同的导出格式。模板具有继承规则, 使你可以为格式相似的页面定义父模板和子模板。
Jinja模板具有语句, 表达式和(可选)注释。由{%statement%}定义的语句定义模板结构。由{{expression}}定义的表达式会用你的数据填充模板。由{#comment#}定义的注释不会显示在输出中-它们仅在模板内部。
nbconvert是一个Python库, 可让你将Jupyter Notebook转换为其他格式, 例如HTML, LaTeX和PDF。 nbconvert使用Jinja模板定义如何以这些格式显示Jupyter Notebook。你可以使用继承定义自定义模板或扩展默认的Jupyter模板。
现在, 你可以开始制作自己的模板并导出漂亮的Jupyter Notebook文档了!
参考文献:
Jinja2文档
Python模板文档
【使用Jinja2的Jupyter Notebook的自定义模板】nbconvert文档

    推荐阅读