nbconvert 默认将输出图片导出到同名子文件夹(如 notebook_files/)并在 markdown 中用相对路径引用,该路径由默认模板硬编码决定,不受工作目录或notebookapp配置影响。

nbconvert 默认怎么处理图片路径
当你运行 jupyter nbconvert --to markdown notebook.ipynb,nbconvert 会把 notebook 中所有输出图片(比如 matplotlib 生成的图)导出到一个同名子文件夹(如 notebook_files/),并在 Markdown 中用相对路径引用,例如:。这个路径是硬编码在默认模板里的,不是你本地磁盘路径,也不受当前工作目录影响。
想改图片路径?得改输出行为,不是改配置文件
注意:c.NotebookApp.notebook_dir 这类配置只管 Jupyter 启动时的根目录,对 nbconvert 导出时的图片存放位置完全无效。真正起作用的是 nbconvert 的资源管理逻辑和模板。
- 如果只是想让图片放在同一级目录(不建
_files子文件夹),可以用--output-dir=.+ 自定义模板,但默认模板不支持直接“扁平化”存放;更实际的做法是导出后用脚本重命名+移动图片并批量替换 Markdown 中的路径 - 如果 notebook 里图片是 base64 编码(比如复制粘贴进 Markdown 单元格),nbconvert 默认会原样保留 base64 字符串,不生成外部文件——这种情况下根本没“路径”可改
- 如果图片来自
这类本地引用,nbconvert 默认不会复制这些文件,Markdown 里路径保持原样,是否能显示取决于最终渲染环境的相对路径结构
真正可控的方式:用自定义 Jinja2 模板
nbconvert 允许你覆盖图片资源的写入逻辑。你需要一个轻量模板,比如新建 flat_markdown.tpl:
{% extends 'basic.tpl' %}
{% block any_cell %}
{{ super() }}
{% endblock %}
{% block write_figure %}
{%- if resources['outputs'] %}
{%- for key, value in resources['outputs'].items() %}
{%- if key.endswith('.png') or key.endswith('.jpg') or key.endswith('.svg') %}
@@##@@
{%- endif %}
{%- endfor %}
{%- endif %}
{% endblock %}
然后导出时指定它:
jupyter nbconvert --to markdown --template flat_markdown.tpl notebook.ipynb
这样图片不会被挪进 _files,而是保留在原路径(或由你控制写入位置),Markdown 中也只保留原始文件名,后续可统一移动图片并调整相对关系。
容易忽略的坑:HTML 和 Markdown 对路径的解析差异
导出为 HTML 时,nbconvert 把图片嵌入 data:image/png;base64,... 或按需复制到 _files/;但导出为 Markdown 时,它只做静态路径映射,不做文件搬运决策。这意味着:
- 你手动改了 Markdown 里的
路径,但没同步移动真实图片文件 → 渲染时 404 - 用了
--no-input或--no-prompt,但 notebook 里有输出图 → 图片仍会被导出到_files/,路径不变 - 在 GitHub 或 CSDN 上预览 Markdown,它们不执行 nbconvert,只读原始文本 → 所有相对路径必须符合平台约定(比如 GitHub 要求图片和 md 在同一仓库层级)
最稳妥的做法不是强行“改路径”,而是导出后用 Python 脚本统一规整:读取 Markdown、提取所有 、按规则重命名图片、更新路径字符串、保存——这才是生产环境里真正可控的环节。











