执行前提:执行 Notebook 会运行其中的代码。请先确认文件及依赖可信,并在合适的隔离环境和资源限制下运行。示例中的 notebook_filename、run_path 与 notebook_filename_out 需要替换或定义为实际输入、工作目录和输出路径;保存操作可能覆盖同名输出文件。
Jupyter Notebook 经常以清空输出单元格的状态保存。nbconvert 提供了一种方便的方法:执行 .ipynb Notebook 文件的输入单元格,再将输入与输出单元格一起保存为 .ipynb 文件。
本节演示如何执行 .ipynb 文档,并以 Notebook 格式保存结果。如果需要导出为 reStructuredText、Markdown 等其他格式,并选择是否执行,请参阅 将 nbconvert 用作库。执行 Notebook 很有用,例如一次运行 Python 库中的全部 Notebook,或者自动完成涉及多个 Notebook 的项目的数据分析。
从命令行执行 Notebook
执行 Notebook 的相同功能同时提供命令行接口和 Python API。例如,可以使用以下命令执行一个 Notebook:
jupyter nbconvert --to notebook --execute mynotebook.ipynb
通过 Python API 执行 Notebook
本节介绍 Python API。
完整示例
先从一个完整的快速示例开始,细节将在后面说明。
导入:首先导入 nbconvert 和 ExecutePreprocessor 类:
import nbformat
from nbconvert.preprocessors import ExecutePreprocessor
加载:假设 notebook_filename 保存了 Notebook 路径,可以这样加载:
with open(notebook_filename) as f:
nb = nbformat.read(f, as_version=4)
配置:接着配置 Notebook 的执行方式:
ep = ExecutePreprocessor(timeout=600, kernel_name='python3')
这里指定了两个可选参数 timeout 和 kernel_name,分别定义单元格执行超时时间和执行内核。
执行(预处理):真正运行 Notebook 时,调用 preprocess() 方法:
ep.preprocess(nb, {'metadata': {'path': 'notebooks/'}})
理想情况下,执行过程中不会出现错误;错误处理见最后一节。注意,path 指定 Notebook 执行时所在的文件夹。
保存:最后保存执行后的 Notebook:
with open('executed_notebook.ipynb', 'w', encoding='utf-8') as f:
nbformat.write(nb, f)
至此,执行后的 Notebook 会保存到当前文件夹中的 executed_notebook.ipynb 文件。
执行参数:traitlets
传给 ExecutePreprocessor 的参数是一类称为 traitlets 的配置选项。traitlets 有许多便利之处:例如约束输入类型,并能作为类属性访问或修改。每个 traitlet 还会自动暴露为命令行选项。例如,从命令行传入超时时间:
jupyter nbconvert --ExecutePreprocessor.timeout=600 --to notebook --execute mynotebook.ipynb
下面详细介绍刚才使用的两个 traitlet。
timeout 定义每个 Notebook 单元格允许运行的最长时间,单位为秒。超过此时间就会抛出异常。原文所述默认值为 30 秒;遇到运行时间较长的单元格时,可以设置更大的值。也可以将 timeout 设为 None 或 -1,取消执行时间限制。
版本校注:教程正文的“30 秒”与同版本 7.17.1 配置参考不一致;配置参考列出的 ExecutePreprocessor.timeout 默认值为 None,即不设该超时,且 timeout_func 可覆盖它。实际任务应像前面的示例一样显式设置合适的超时,不应依赖这里的历史默认值描述。
kernel_name 用于指定执行时使用的内核名称。默认情况下,内核名称来自 Notebook 元数据;设置该 traitlet 可以用用户指定的内核覆盖元数据中的值。常见场景是兼容 Python 2/3 的库带有用于文档或测试的 Notebook。这些 Notebook 的元数据会注明 python2 或 python3,取决于上次保存时使用的内核。实际上,它们可能同时适用于 Python 2 和 Python 3,而测试时需要能以编程方式在两个版本中执行。此时,kernel_name 可简化流程并保持一致:先以 python2 为内核运行一次,再以 python3 运行一次。
处理错误与异常
前面展示了在没有执行错误时保存已执行的 Notebook。如果出现错误,该怎么办?
执行到首个错误
默认情况下,执行过程中出现错误会停止执行并抛出 CellExecutionError。导致错误的源单元格,以及原始错误名称和消息也会一并打印出来。出现错误后,仍然可以按前面的方法保存 Notebook:
with open('executed_notebook.ipynb', mode='w', encoding='utf-8') as f:
nbformat.write(nb, f)
保存的 Notebook 包含直到失败单元格为止的输出,也包含完整的堆栈跟踪和错误信息,可用于调试。
处理错误
以下模式适合在处理错误的同时执行 Notebook:
from nbconvert.preprocessors import CellExecutionError
try:
out = ep.preprocess(nb, {'metadata': {'path': run_path}})
except CellExecutionError:
out = None
msg = 'Error executing the notebook "%s".\n\n' % notebook_filename
msg += 'See notebook "%s" for the traceback.' % notebook_filename_out
print(msg)
raise
finally:
with open(notebook_filename_out, mode='w', encoding='utf-8') as f:
nbformat.write(nb, f)
无论是否发生执行错误,都会保存执行后的 Notebook。不过,如果发生错误,还会打印一条额外消息并再次抛出 CellExecutionError。该消息引导用户查看保存的 Notebook,以进一步检查问题。
执行到底并保存所有错误
有时需要执行会抛出异常的 Notebook,例如展示一种错误情形。此时可以使用默认值为 False 的 allow_errors traitlet,让程序不在首个错误处停止。设置 allow_errors=True 后,Notebook 会执行到最后,不论期间是否发生错误。输出 Notebook 会保存所有抛出异常的单元格的堆栈跟踪和错误消息。
范围说明:allow_errors=True 处理的是单元格执行错误,并不代表内核启动失败、执行超时或输出文件写入失败等情况都能被忽略。错误处理示例中的 finally 会尝试保存,但文件系统错误仍可能使保存失败。
Widget 状态
如果 Notebook 包含 Jupyter Widgets,可以将全部 Widget 的状态存储在 Notebook 元数据中。这使得 nbviewer 或转换后的 HTML 可以呈现可交互的 Widget。
使用 store_widget_state 参数,可以让 nbconvert 不存储这些状态:
jupyter nbconvert --ExecutePreprocessor.store_widget_state=False --to notebook --execute mynotebook.ipynb
执行过程中不会在浏览器中进行 Widget 渲染,因此只会计算 Widget 的默认状态或由用户代码修改的状态。%%javascript 单元格将在 Notebook 渲染时执行,从而让复杂交互在 UI 中查看时按预期工作。
如果执行后无法查看 Widget 结果,可能需要在菜单中选择 File → Trust Notebook(文件 → 信任 Notebook)。
只有在确认 Notebook 及输出内容可信后,才应执行“信任 Notebook”。信任操作不是对未知文件的安全检查,也不能代替审阅。












暂无评论内容