拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Bokeh Application Handler 基类详解:构建自定义 Document 生成器的核心机制

Bokeh Application Handler 基类详解构建自定义 Document 生成器的核心机制【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh导读bokeh.application.handlers.handler.Handler是 Bokeh 服务端应用Bokeh Server Application的基石抽象每当 Bokeh 服务器为一个新会话创建 Document 时Application 会把一个全新的空 Document 依次交给其注册的每个 Handler 的modify_document方法进行填充全部完成后该 Document 才被用于服务用户会话。本文以 Bokeh 仓库中 handler.rst 对应模块为骨架深入剖析Handler基类的全部属性与方法契约讲解如何编写自定义 Handler含基于数据库数据初始化文档的完整示例并结合仓库源码说明内置 Handler 家族、错误处理与测试验证机制。读完本文你将掌握 Bokeh 应用处理器的生命周期模型并具备编写可嵌入 Bokeh Server 的自定义 Handler 的实战能力。Handler 在 Bokeh 应用中的核心定位在 Bokeh 中Application是 Document 实例的工厂factory。整个会话建立流程如下见 handler.py 模块 docstring 与 application.py 模块 docstringBokeh 服务器收到一个会话请求向 Application 索要一个新的 DocumentApplication 创建一个空 Document该 Document 被依次传给每个 Handler 的modify_document(doc)方法所有 Handler 都更新完 Document 后这个 Document 就被用于服务该用户会话。这一空 Document → 逐处理器填充 → 交付会话的管线模型是理解 Bokeh 服务端一切应用构建方式的前提。Application通过其initialize_document方法application.py按注册顺序循环调用每个 handler 的modify_document并在每个 handler 执行后检查其failed标志若有失败则记录错误日志最后在文档校验开启时调用doc.validate()。Handler基类正是这一管线中所有处理器的统一抽象它定义了每个处理器必须遵守的接口契约同时以模板方法的形式预留了可供子类覆盖的生命周期钩子。Handler 基类 API 全景Handler类定义于 src/bokeh/application/handlers/handler.py其类 docstring 只有一句核心表述为 Bokeh 应用构建新 Bokeh Document 提供一种机制Provide a mechanism for Bokeh applications to build up new Bokeh Documents。状态属性Handler 内部用下划线私有字段维护状态并通过只读属性暴露给外部属性类型说明failedbool处理器是否未能成功修改文档对应内部_failed初始为Falseerrorstr \| None处理器失败时可能携带的相关错误消息对应_error初始为Noneerror_detailstr \| None处理器失败时可能携带的 traceback 或其他细节对应_error_detail初始为Nonesafe_to_forkboolBokeh 服务器是否仍可安全 fork 新 worker。基类恒返回True子类通常在代码已执行后返回Falsestatic_path方法str \| None应用专属静态资源路径基类实现中若failed为真则返回None否则返回内部_static构造函数Handler()将_failed、_error、_error_detail、_static全部初始化为None或False不做其他任何工作因此基类本身是一个空操作处理器可以直接实例化作为 no-op 占位例如 DirectoryHandler 在没有生命周期钩子文件时就用Handler()充当空生命周期处理器。必须实现的抽象方法modify_documentmodify_document(self, doc: Document) - None是唯一要求子类必须实现的方法基类直接抛出NotImplementedError(implement modify_document())。其契约要点参数一个需要被就地in-place更新的 Bokeh Document语义子类通过向文档添加 root 模型、设置主题、模板等方式填充内容返回值虽然 docstring 标注返回 Document但实际实现以就地修改为主子类约定返回传入的 doc 即可。单元测试 明确验证了基类modify_document会抛出NotImplementedError。生命周期钩子服务器级与会话级Handler 提供了四个默认为空实现的钩子方法子类可按需覆盖钩子方法触发时机参数默认行为on_server_loaded(server_context)服务器首次启动时创建任何会话之前ServerContext空操作passon_server_unloaded(server_context)服务器干净退出时停止 IOLoop 之前ServerContext空操作passdocstring 特别警告实际中服务器常被信号杀死此代码可能不会运行on_session_created(session_context)新会话创建时modify_document被调用之前SessionContext空操作passasync 方法on_session_destroyed(session_context)会话销毁时SessionContext空操作passasync 方法这些钩子由Application在相应时机逐一转发给每个 handler见 application.py 中on_server_loaded、on_server_unloaded、on_session_created、on_session_destroyed的实现并且on_session_created若返回 Future 会延迟会话创建直至其完成。请求处理与 URL 约定process_request(request) - dict处理传入的 HTTP 请求返回一个要并入 session_context 的附加数据字典必须 JSON 可序列化。基类默认返回空字典{}。Application.process_request会将所有 handler 返回的字典依次update合并application.py。url_path() - str | None告知 Bokeh 应用该 handler 应被安装到哪个 URL 路径基类默认返回None。若多个 handler 都指定了url_pathApplication 只采用 handler 列表中的第一个值。实战编写自定义 Handler数据库驱动示例模块 docstring 给出了一个非常典型的自定义 Handler 轮廓——从数据库查询信息来初始化文档from bokeh.application.handlers.handler import Handler class DatabaseHandler(Handler): A Bokeh Application handler to initialize Documents from a database def modify_document(self, doc: Document) - None: # do some data base lookup here to generate plot # add the plot to the document (i.e modify the document) doc.add_root(plot)编写自定义 Handler 的要点继承Handler并实现modify_document在方法内完成数据获取数据库查询、文件读取、API 调用等用doc.add_root(...)等方法就地修改传入的 Document而不是替换它。完成自定义 Handler 后可以通过Application编程式地嵌入 Bokeh Serverfrom bokeh.application import Application from bokeh.server.server import Server from tornado.ioloop import IOLoop app Application(DatabaseHandler()) server Server({/myapp: app}, io_loopIOLoop.current()) server.start()这与仓库中 FunctionHandler 的 docstring 展示的嵌入模式一致Application(FunctionHandler(make_doc))配合Server({/bkapp: app}, io_loopIOLoop.current())即可在任意 Python 程序中启动 Bokeh Server。更完整的可运行示例见仓库examples/server/api目录如 server_document 等 API 示例。内置 Handler 家族基类的典型子类Handler基类在 handlers 包 中被多个具体处理器继承理解这些子类有助于把握基类各钩子的真实用法FunctionHandlerfunction.py接收一个纯 Python 函数func(doc)用于修改文档支持trap_exceptions参数决定异常是捕获记录调用handle_exception还是向上传播其safe_to_fork在modify_document首次执行后变为False。该 Handler 不被bokeh serve命令行工具使用专为编程式嵌入设计。ScriptHandlerscript.py读取.py脚本文件源码脚本执行时当前 Document 以curdoc形式可用传入的argv以sys.argv形式可用。CodeHandlercode.pyScriptHandler的父类编译并执行 Python 源码它会把脚本中的output_notebook、output_file、show、save、reset_output等 IO 函数 monkey-patch 成带警告的 no-op_io_functions列表并检查脚本是否替换了输出文档若curdoc() is not doc则抛RuntimeError其url_path返回/ 文件名去扩展名。NotebookHandler与 ScriptHandler 对应用于执行.ipynb笔记本文件。DirectoryHandlerdirectory.py加载一个应用目录目录内可含main.py或main.ipynb、可选的server_lifecycle.py/app_hooks.py钩子模块二者不可同时存在、static静态资源目录、theme.yaml主题文件与templates/index.html模板其modify_document会自动将主题和模板配置到文档上。典型目录布局myapp | ---main.py ---server_lifecycle.py ---static ---theme.yaml ---templates ---index.htmlServerLifecycleHandlerserver_lifecycle.py从server_lifecycle.py模块中提取on_server_loaded、on_server_unloaded、on_session_created、on_session_destroyed四个回调并注册还会用_check_callback校验各回调的签名参数。DocumentLifecycleHandlerdocument_lifecycle.py调用 Document 上注册的on_session_destroyed回调执行后清空回调集合并触发一次垃圾回收。这些子类共同印证了基类的设计意图Handler 是文档修改能力 生命周期钩子 请求数据 URL/静态资源声明的组合抽象具体策略脚本、函数、目录、笔记本由子类决定。错误处理机制handle_exception 与 CodeRunner当处理器执行失败时Bokeh 通过模块级函数handle_exception(handler, e)handler.py统一记录异常将 handler 的_failed置为True用traceback.format_exc()填充_error_detail从 traceback 末帧提取filename、line_number、func与源码行组合出带文件、行号、函数名与代码行的_error消息。handle_exception的形参类型为Handler | CodeRunner说明它既服务于 Handler 本身也服务于 CodeRunner 这一编译并运行 Python 源码的工具类ScriptHandler/NotebookHandler 的底层执行器持有ran、_failed、_error、_error_detail等状态。FunctionHandler在trap_exceptionsTrue时即调用此函数记录异常而Application.initialize_document在 handler 失败后会用h.error与h.error_detail输出错误日志——三者构成了捕获 → 记录 → 上报的完整错误链路。单元测试对基类契约的验证仓库在 tests/unit/bokeh/application/handlers/test_handler.py 中用 pytest 对基类契约做了系统性验证test_create新建 Handler 后failed为False、url_path()/static_path()为None、error/error_detail为Nonetest_modify_document_abstract调用基类modify_document抛出NotImplementedErrortest_default_server_hooks_return_none与test_default_sesssion_hooks_return_none四个生命周期钩子默认返回None其中会话级钩子为 async需awaittest_static_path手动设置_static后返回该路径一旦_failed True则返回Nonetest_process_request基类process_request返回空字典{}。这些测试从行为层面锁定了基类的默认实现是阅读源码时最直接的契约说明书。同目录下 test_function.py、test_script.py、test_directory.py、test_code.py 等则分别验证了各内置 Handler 子类。小结bokeh.application.handlers.handler.Handler是 Bokeh 服务端应用的统一抽象层它以modify_document为必选契约以on_server_loaded、on_server_unloaded、on_session_created、on_session_destroyed为可选生命周期钩子以process_request、url_path、static_path为辅助能力声明配合handle_exception错误记录机制构建出可扩展的 Document 生成管线。无论你是通过bokeh serve运行目录应用还是编程式嵌入 Server理解这个基类都是深入掌握 Bokeh 应用架构的关键一步——在此基础上你可以像DatabaseHandler示例那样自由地为任何数据源定制文档初始化逻辑。【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门