深入解析 Bokeh 文档画廊系统:gallery_detail.rst 模板如何驱动示例页面自动生成

发布时间:2026/9/14 18:10:15

深入解析 Bokeh 文档画廊系统:gallery_detail.rst 模板如何驱动示例页面自动生成 深入解析 Bokeh 文档画廊系统gallery_detail.rst 模板如何驱动示例页面自动生成【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh导读Bokeh 官方文档中那张琳琅满目的示例画廊Gallery页面并不是人工逐个书写的而是由 Sphinx 扩展在文档构建阶段自动批量生成的。本文以 Bokeh 仓库中负责单个示例详情页的 Jinja2 模板 gallery_detail.rst 为核心完整讲解从gallery.json配置、bokeh-gallery指令扫描、模板渲染到bokeh-plot指令执行示例代码、输出交互图与源码块的全链路机制。读完本文你将掌握 Bokeh 画廊的底层工作原理并能在自己的 Sphinx 文档项目中复刻这套配置驱动 模板生成的示例文档流水线。一、gallery_detail.rst单个示例详情页的完整模板gallery_detail.rst位于 src/bokeh/sphinxext/_internal/_templates/gallery_detail.rst全文只有 13 行却承担着为画廊中每一个示例生成独立 RST 详情页的重任。先看它的完整内容:orphan: .. index:: single: examples; {{ filename }} {{ ref }} {{ filename }} {{ - * filename|length }} .. bokeh-plot:: {{ source_path }} :process-docstring: :source-position: below这是一个 Jinja2 模板由三个变量驱动逐行拆解如下行内容作用:orphan:声明该页面是孤儿文档即使没有被任何 toctree 引用Sphinx 也不会发出警告。画廊详情页是程序批量生成的不参与目录树因此必须加此标记.. index:: single: examples; {{ filename }}为 Sphinx 生成索引条目把filename示例名登记到examples索引分组下方便文档内联搜索{{ ref }}插入由生成器构造的 RST 锚点引用形如.. _example_markers_basic_scatters:供其他页面用:ref:交叉引用定位该示例{{ filename }}{{ - * filename\|length }}用示例文件名作为页面标题并用等长的-生成 RST 二级标题下划线.. bokeh-plot:: {{ source_path }}核心指令指向示例 Python 源文件的绝对路径由 Sphinx 扩展实际执行该脚本:process-docstring:布尔选项把示例文件顶部的模块 docstring 单独渲染为格式化说明块:source-position: below枚举选项将格式化后的源码块放在图表下方模板虽然简短但孤儿文档 索引登记 交叉引用锚点 可执行代码指令四个要素缺一不可构成了每个示例页的完整骨架。二、模板从何而来bokeh_gallery 扩展的生成流程gallery_detail.rst 本身不直接出现在文档源码树中而是由 Sphinx 扩展 bokeh_gallery.py 在config-inited阶段动态写出的。该扩展在文档的 conf.py 中通过bokeh.sphinxext._internal.bokeh_gallery注册。2.1 关键数据结构GalleryDetail生成器内部用 TypedDict 描述每个示例的元信息见 bokeh_gallery.pyclass GalleryDetail(TypedDict): name: str # 示例文件名不含 .py path: str # 相对仓库根的路径如 examples/basic/scatters/markers.py ref: str # RST 锚点如 .. _example_markers_basic_scatters: rst_file_path: str # 生成的目标文件相对路径如 basic/scatters/markers.rst2.2 核心函数 get_details扫描示例目录get_details(app)bokeh_gallery.py遍历conf.py中配置的bokeh_example_subdirs列表对每个子目录中的文件做三件事过滤跳过以_开头的文件、非.py文件以及在bokeh_sampledata_xref_skiplist中的示例构造锚点生成ref f.. _example_{name}_{subdir}:形式的交叉引用标签产出条目组装成GalleryDetail并汇总返回。以实际目录 examples/basic/scatters 为例扫描后会产生markers.rst、color_scatter.rst、elements.rst、image_url.rst等条目锚点分别为.. _example_markers_basic_scatters:等。2.3 config_inited_handler写文件与增量构建config_inited_handlerbokeh_gallery.py在 Sphinx 配置初始化后执行完整的生成逻辑检查画廊配置文件gallery.json是否存在缺失则抛SphinxError用ensuredir创建画廊目录docs/gallery与示例目录docs/examples含所有子目录用一个extras集合记录目录中已存在的文件用于构建后清理残留对每个GalleryDetail渲染模板并写入文件source_path abspath(join(app.srcdir, .., .., .., detail[path])) f.write(GALLERY_DETAIL.render(filenamedetail[name], source_pathsource_path, refdetail[ref]))注意这里source_path被换算成绝对路径相对文档源码目录向上三级回到仓库根这样bokeh-plot指令才能准确读取examples/...下的示例脚本。增量构建优化如果目标详情文件已存在且其 mtime 比gallery.json新则跳过重写见第 145 行getmtime判断构建结束后删除extras中剩余文件即本次不再生成的历史残留保持画廊目录干净。渲染时的模板对象来自 templates.py即GALLERY_DETAIL _env.get_template(gallery_detail.rst)三、Gallery 索引页与 gallery_detail 的联动画廊的入口页面 docs/bokeh/source/docs/gallery.rst 本身不含任何示例内容只通过bokeh-gallery指令声明要展示哪些目录下的示例.. tab-set:: :class: bk-gallery-tabs .. tab-item:: Basic plotting .. bokeh-gallery:: basic/scatters basic/lines basic/data basic/axes basic/bars basic/areas basic/layouts basic/annotations3.1 BokehGalleryDirective读取 gallery.jsonBokehGalleryDirectivebokeh_gallery.py运行时定位当前文档所在目录下的gallery.json即 docs/bokeh/source/docs/gallery.json解析指令 content 中列出的每个location如basic/scatters到 JSON 中查找对应的示例条目数组对每个条目构造缩略图选项url默认指向examples/.../*.html若条目含url字段则直接使用并新窗口打开、img、alt、title缺省用文件名 stem、desc用索引页模板gallery_page.rst渲染出整张缩略图网格。3.2 gallery_page.rst缩略图网格模板配套的索引模板 gallery_page.rst 生成如下 HTML 结构节选div classbk-gallery div classbk-thumbnail a href... img classgallery width300 height300 src../_images/{{ opt[img] }}.png srcset../_images/{{ opt[img] }}.png, ../_images/{{ opt[img] }}2x.png 2x alt{{ opt[alt] }} /a div classbk-thumbnail-title{{ opt[title] }}/div div classbk-thumbnail-description{{ opt[desc] }}/div /div /div可见它支持1x/2x 高清缩略图srcset、可选的标题与描述说明。而server/app这类远程 Demo 条目见 gallery.json则带url与desc字段点击后跳转到demo.bokeh.org上的在线演示——这正是BokehGalleryDirective中url in detail分支处理的场景。四、bokeh-plot 指令示例页的执行引擎gallery_detail.rst 中真正跑代码的是.. bokeh-plot::指令其实现位于 bokeh_plot.py。该指令同时支持两种用法用法一指向外部示例文件画廊页采用此方式.. bokeh-plot:: path/to/plot.py用法二内联代码.. bokeh-plot:: from bokeh.plotting import figure, output_file, show output_file(example.html) x [1, 2, 3, 4, 5] y [6, 7, 6, 4, 5] p figure(titleexample, width300, height300) p.line(x, y, line_width2) p.scatter(x, y, size10, fill_colorwhite) show(p)两种方式不能混用同时给出参数与 content 会抛出SphinxError见 bokeh_plot.py。另外 Bokeh 文档内部约定了一个__REPO__/前缀路径以它开头时会被解析为仓库根目录下的相对路径便于文档源码树内引用。4.1 指令选项option_specBokehPlotDirective在 bokeh_plot.py 中定义了完整的选项规格选项取值默认说明:process-docstring:布尔flag无是否将示例文件的模块 docstring 单独渲染为格式化说明块:source-position:above/below/nonebelow格式化源码块放在图表上方、下方还是不显示:linenos:布尔flag无源码块是否显示行号gallery_detail.rst 固定使用:process-docstring:与:source-position: below即说明文字在上、交互图居中、源码在下的经典示例页布局。process_code_blockbokeh_plot.py还负责把 docstring 从源码中剥离_remove_module_docstring避免展示源码时重复出现模块说明。4.2 执行流水线从源码到交互图run()方法的完整调用链bokeh_plot.pyprocess_args_or_content()—— 确定源码与路径来源process_source()—— 依次执行_evaluate_source()调用ExampleHandler运行示例代码产生一个 BokehDocument并要求文档根节点恰好一个len(d.roots) ! 1时报错读取_sphinx_height_hint()获取图表高度提示调用autoload_static(root, RESOURCES, js_filename)生成独立的 JS 文件与script标签构造autoload_script节点将script_tag直接嵌入 HTML必要时用height_hint包一层div styleheight:...px;process_sampledata()正则扫描源码中的sampledata引用登记到all_sampledata_xrefs与all_gallery_overview供后续采样数据交叉引用生成见 bokeh_plot.py返回target intro above autoload below节点序列即锚点 → docstring 说明 → 源码块可选上方→ 交互图 → 源码块可选下方。最终页面结构因此是交叉引用锚点 → 模块 docstring 说明 → 可交互 Bokeh 图通过 autoload 脚本懒加载 JS→ 缩进格式化的 Python 源码块。4.3 ExampleHandler如何安全执行示例脚本示例脚本包含show(p)、output_file(...)等 I/O 调用直接运行会弹浏览器、写文件因此 example_handler.py 提供了ExampleHandler——一个精简版 Bokeh application handler继承Handler内部用CodeRunner编译执行源码记录error/error_detail/docMonkeypatch 策略见_monkeypatchexample_handler.pyoutput_notebook、output_file、reset_output被替换为空操作_passshow、save被替换为_add_root即把对象直接加入当前curdoc()bokeh.document.Document被替换为返回当前文档的_curdoc由于这些函数从bokeh.io传递导入到bokeh.plotting两个模块都会被同时打补丁执行完成后在finally中恢复原函数并还原curdoc确保文档构建环境不被污染。这就是画廊示例页能静默产出图表而不触发任何浏览器或文件输出的原因。五、实际配置conf.py 中的画廊开关Bokeh 文档构建在 conf.py 中配置了整套画廊参数extensions [ ... bokeh.sphinxext.bokeh_plot, bokeh.sphinxext._internal.bokeh_gallery, ... ] bokeh_example_subdirs [ advanced/extensions, basic/annotations, basic/areas, basic/axes, basic/bars, basic/data, basic/layouts, basic/lines, basic/scatters, styling/visuals, styling/plots, styling/mathtext, styling/themes, interaction/js_callbacks, interaction/legends, interaction/linking, interaction/tools, interaction/tooltips, interaction/widgets, models, plotting, output/webgl, topics/categorical, topics/hierarchical, topics/contour, topics/geo, topics/graph, topics/hex, topics/images, topics/pie, topics/stats, topics/timeseries, ] bokeh_missing_google_api_key_ok False bokeh_sampledata_xref_skiplist [ examples/basic/data/ajax_source.py, examples/basic/data/server_sent_events_source.py, examples/basic/layouts/custom_layout.py, examples/styling/dom/css_classes.py, examples/models/widgets.py, ]各配置项含义注册于 bokeh_gallery.py 的setup与 bokeh_plot.py配置项默认值作用bokeh_gallery_dirdocs/gallery画廊详情页的输出目录bokeh_examples_dirdocs/examples生成示例页的目录bokeh_example_subdirs[]需要扫描生成画廊条目的示例子目录列表bokeh_sampledata_xref_skiplist[]跳过采样数据交叉引用的示例路径黑名单bokeh_missing_google_api_key_okTrue见 bokeh_plot.py缺少GOOGLE_API_KEY时是否允许继续构建Bokeh 自身文档将其设为False强制校验若gallery.json缺失config_inited_handler会直接报错可见该文件是画廊系统的配置中枢。六、把新示例加入画廊端到端步骤结合以上源码往画廊中添加一个新示例的完整流程为写示例脚本在 examples 下相应子目录创建my_plot.py文件顶部用模块 docstring 书写说明文字会作为详情页的说明块脚本末尾调用show(p)登记目录确保该子目录如basic/scatters出现在 conf.py 的bokeh_example_subdirs中配置缩略图信息在 gallery.json 对应location数组中追加条目{ name: my_plot.py, alt: Thumbnail link to the examples/basic/scatters/my_plot.py example ... }title、desc、url均为可选字段其中url存在时会作为外部链接新窗口打开 4.在画廊索引页声明在 gallery.rst 对应tab-item的.. bokeh-gallery::下追加basic/scatters若已声明则跳过 5.重新构建文档config_inited_handler扫描目录 → 渲染gallery_detail.rst生成docs/examples/basic/scatters/my_plot.rst→bokeh-plot执行示例并输出交互图与源码块若该文件已存在且较新则跳过增量构建。七、构建性能与并行安全画廊系统为文档构建做了两方面性能考量增量写入详情文件比gallery.json新则跳过重写避免每次全量重建耗时统计与预警BokehPlotDirective记录每个示例的total/evaluate/serialize/write四段耗时_PlotTiming见 bokeh_plot.py在build-finished阶段汇总输出总耗时并用nlargest(5, ...)列出最慢的 5 个示例便于定位拖慢文档构建的脚本。此外两个扩展的setup都返回PARALLEL_SAFE明确声明支持 Sphinx 并行构建同时通过env_merge_info正确合并并行子进程的bokeh_plot_files与耗时数据bokeh_plot.py保证并行模式下生成的 JS 资源与统计信息不丢失。八、总结一套可复用的配置驱动示例文档范式从 gallery_detail.rst 这个 13 行模板出发可以看到 Bokeh 文档团队搭建的完整示例文档流水线数据驱动gallery.json定义画廊内容与元数据conf.py 定义扫描范围模板驱动gallery_detail.rst负责单个示例页gallery_page.rst 负责索引缩略图代码驱动bokeh_gallery.py 批量生成页面bokeh_plot.py 与 example_handler.py 负责安全执行示例并产出可交互图表。这套模式的核心价值在于新增一个示例只需写脚本 改一行 JSON页面、锚点、索引、缩略图全部自动生成且天然支持增量构建与并行构建。对于任何希望以示例即文档方式维护技术文档的 Sphinx 项目Bokeh 这套从模板到指令再到执行器的实现都是一份可直接借鉴的完整范本。相关测试与构建入口可进一步参考 tests/codebase 与 docs/bokeh/Makefile 深入了解。【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/14 18:10:15

OpenClaw开源AI助手框架部署与插件开发指南

1. OpenClaw项目概述OpenClaw是一个完全开源的多功能AI助手框架,它最吸引人的特点是提供了6000可扩展的技能插件。这个项目最初由腾讯云团队孵化,现在已经成为GitHub上最活跃的AI开源项目之一。我最近在本地环境完整部署了OpenClaw,实测下来它…

2026/9/14 18:10:15

Java使用Zookeeper实现微服务注册与发现

1. 项目概述在分布式系统中,服务注册与发现是微服务架构的核心组件之一。Zookeeper作为一个高可用的分布式协调服务,常被用作服务注册中心。本文将详细介绍如何使用Java操作Zookeeper实现完整的服务注册与发现方案,重点讲解Curator框架的使用…

2026/9/14 18:40:19

Python图像处理入门:Pillow库基础与应用

1. Python图形处理入门:PIL/Pillow基础解析 计算机图形处理是当代编程中的必备技能,而Python生态中的PIL(Python Imaging Library)及其分支Pillow无疑是这个领域最受欢迎的库之一。作为处理图像的基础工具,它们提供了…

2026/9/14 18:40:19

Java数据类型存储与位运算实战指南

1. Java数据存储基础原理在Java中,数据存储的核心在于理解基本数据类型在内存中的表示方式。以int类型为例,它占用4个字节(32位)的存储空间。当我们声明int a 21时,计算机会将这个值转换为二进制形式存储:…

2026/9/14 18:40:19

如何在 Windows 上安装 MongoDB 并连接本地服务?

如何在 Windows 上安装 MongoDB 并连接本地服务? 【免费下载链接】toBeBetterJavaer 一份通俗易懂、风趣幽默的Java学习指南,内容涵盖Java基础、Java并发编程、Java虚拟机、Java企业级开发、Java面试等核心知识点。学Java,就认准二哥的Java进…

2026/9/14 18:35:19

xManager 上手指南:3分钟任意升级、降级与安装Spotify版本

xManager 上手指南:3分钟任意升级、降级与安装Spotify版本 【免费下载链接】xManager Ad-Free, New Features & Freedom 项目地址: https://gitcode.com/GitHub_Trending/xm/xManager 想换一个指定版本的Spotify——比如尝鲜新功能,或者回到某…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码