我正在尝试以编程方式生成笔记本,执行它,然后使用 nbformat 转换为 HTML。
代码基本上是这样的:
import nbformat as nbf
from nbconvert.preprocessors import ExecutePreprocessor
from nbconvert import HTMLExporter
nb = nbf.v4.new_notebook()
nb.cells = [nbf.v4.new_code_cell("""
import altair as alt
alt.renderers.enable("notebook")
# ... load df
alt.Chart(df).mark_point().encode(x='x', y='y')
""")]
ep = ExecutePreprocessor(timeout=600, kernel_name='python3')
ep.preprocess(nb, {'metadata': {'path': '.'}})
html_exporter = HTMLExporter()
html_exporter.template_file = 'basic'
(body, resources) = html_exporter.from_notebook_node(nb)
with open('out.html', 'w') as f:
f.write(body)
该流程工作正常,它生成一个笔记本和一个 HTML 文件,并且所有代码都被执行。但是,代码单元的输出如下(无图表):
<vega.vegalite.VegaLite at 0x7f80c4d8a090>
当我将笔记本写为 .ipynb 文件并手动执行时,在相同的环境中,图表按预期显示。可以这样使用 Altair 吗?我想知道我在 Python session 中运行 nbformat 是否会产生影响,也许它只能在浏览器中呈现图表?
最佳答案
通过 nbformat 生成笔记本和实时运行笔记本之间的区别在于 nbformat 没有附加前端。这在这里很重要,因为对于 Altair 图表,前端笔记本扩展是渲染图表的工具。
那么为什么生成图表后打开笔记本时没有显示渲染的图表呢?这是因为 Jupyter 笔记本的安全模型:打开新的不受信任的笔记本时,笔记本不会执行现有的 Javascript,因为这将是一个简单的攻击路径(例如,攻击者可以发布带有 javascript 的笔记本,该笔记本在加载时执行 python在您有机会阅读笔记本内容之前,在您的硬盘驱动器中搜索敏感信息并将其邮寄给攻击者的代码)。
因此,在渲染图表时,vega 笔记本扩展会生成 PNG 预览并将其保存到笔记本中,因此当您与其他人共享它时,他们会获得静态图表预览作为占位符,直到他们实际执行笔记本。 但是,如果您在没有前端的情况下执行笔记本,则不会生成此 PNG 预览,因此打开笔记本时您看不到任何内容。
解决这个问题的最佳方法是使用 JupyterLab 而不是 Juptyer Notebook。在 JupyterLab 中,Altair 图表使用 VegaLite Mimetype 保存,由 vega labextension 解释并转换为图表。这不涉及从笔记本执行任意 javascript,因此您以这种方式创建的图表将在 JupyterLab 加载时在笔记本中呈现。经典笔记本中不使用此路径,因为经典笔记本不支持基于 mimebundle 的渲染。
如果您必须使用 Jupyter Notebook 而不是 JupterLab,除了使用 headless 浏览器引擎(例如 selenium)之外,实际上没有任何方法可以解决此问题。使用浏览器前端以编程方式执行笔记本,该前端将呈现 PNG 预览。
关于python - 使用 nbformat 生成 Jupyter 笔记本 - Altair 图表不显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58807145/