如何用nbconvert在Jupyter Notebook导出PDF时截取单元格输出
解决Jupyter nbconvert转WebPDF时长输出未截断的问题
nbconvert本身没有直接的命令行参数来自动截断单元格长输出,但可以通过以下几种方式实现需求,且无需修改原Notebook的代码内容:
方法1:自定义Jinja2模板修改渲染逻辑
WebPDF转换依赖于HTML模板,你可以修改模板来添加输出截断规则:
- 找到nbconvert的WebPDF模板路径(可通过
jupyter --paths查看配置目录,通常在jupyter/nbconvert/templates/webpdf下) - 复制原模板文件(比如
index.html.j2)到自定义目录,修改其中处理输出的部分:
针对stream类型的输出(比如print生成的内容),添加行数截断逻辑:{% for output in cell.outputs %} {% if output.output_type == 'stream' %} <pre class="output stream"> {% set lines = output.text.split('\n') %} {% if lines|length > 100 %} {{ lines[:100]|join('\n') }} <span style="color: #666;">...(输出已截断,共{{ lines|length }}行)</span> {% else %} {{ output.text }} {% endif %} </pre> {% else %} {# 保留其他类型输出的原有渲染逻辑 #} {{ output|safe }} {% endif %} {% endfor %} - 转换时指定自定义模板:
jupyter nbconvert --to webpdf --allow-chromium-download --template-dir /path/to/your/custom/templates filename.ipynb
方法2:预处理Notebook(生成临时文件转换)
写一个简单的Python脚本,加载原Notebook并截断输出,生成临时Notebook后再转换,原文件不受影响:
import json from copy import deepcopy # 配置截断参数 MAX_OUTPUT_LINES = 100 # 加载原Notebook with open("filename.ipynb", "r", encoding="utf-8") as f: nb = json.load(f) # 遍历单元格处理输出 for cell in nb["cells"]: if cell["cell_type"] == "code" and "outputs" in cell: for output in cell["outputs"]: if output.get("output_type") == "stream": lines = output["text"].split("\n") if len(lines) > MAX_OUTPUT_LINES: output["text"] = "\n".join(lines[:MAX_OUTPUT_LINES]) + "\n...(输出已截断,共{}行)".format(len(lines)) # 保存临时Notebook with open("temp_filename.ipynb", "w", encoding="utf-8") as f: json.dump(nb, f, indent=2) # 转换临时文件 !jupyter nbconvert --to webpdf --allow-chromium-download temp_filename.ipynb
运行脚本后,临时文件会被转换为PDF,原Notebook保持不变。
方法3:自定义nbconvert预处理器
创建一个预处理器类,在转换过程中动态截断输出:
- 创建
truncate_output.py文件:
from nbconvert.preprocessors import Preprocessor class TruncateOutputPreprocessor(Preprocessor): def __init__(self, max_lines=100, **kwargs): self.max_lines = max_lines super().__init__(**kwargs) def preprocess_cell(self, cell, resources, index): if cell.cell_type == "code" and cell.outputs: for output in cell.outputs: if output.output_type == "stream": lines = output.text.split("\n") if len(lines) > self.max_lines: output.text = "\n".join(lines[:self.max_lines]) + f"\n...(输出已截断,共{len(lines)}行)" return cell, resources
- 转换时指定使用该预处理器:
jupyter nbconvert --to webpdf --allow-chromium-download --preprocessor truncate_output.TruncateOutputPreprocessor --preprocessor-args max_lines=100 filename.ipynb
以上三种方法都能在不修改原代码的前提下,实现输出截断,避免生成超大PDF。
内容的提问来源于stack exchange,提问作者user27982201
相关产品推荐
相关产品推荐

