Dash 2.18版本新特性介绍

本文示例代码已上传至我的Github仓库:https://github.com/CNFeffery/dash-master

Gitee同步仓库地址:https://gitee.com/cnfeffery/dash-master

  大家好我是费老师,几个小时前Dash发布了其2.18.0版本,执行下面的命令进行最新版本Dash的安装:

pip install dash -U

  2.18版本中新增了多项重要的新功能,使得我们在开发Dash应用功能时更加的得心应手,下面我们就来一起get其中的重点😉:

1 新增全局/局部回调函数错误处理机制

  从2.18版本开始,Dash新增了针对回调函数的全局/局部错误处理机制,使得我们可以通过自定义的错误处理函数,来更统一便捷的处理回调函数计算逻辑中抛出的错误。

1.1 全局错误处理

  针对全局错误处理,我们可以编写自定义函数,其第一个输入参数接收每次抛出的错误,接着将此函数赋值给dash.Dash()中的on_error参数即可。

  举个简单的例子(对应本文源码app1.py),下面的代码中我们定义了函数handle_global_error(),在其内部基于Dash中的服务端set_props(),将每次错误发生对应的错误触发来源错误信息fac全局提示的形式展示在网页中:

import dash
from dash import html, set_props
import feffery_antd_components as fac
from dash.dependencies import Input, Output
from feffery_dash_utils.style_utils import style

def handle_global_error(e):
    # 利用服务端set_props()将错误信息集中抛出
    set_props(
        "error-message",
        {
            "children": fac.AntdMessage(
                content="触发id {},错误信息 {}".format(dash.ctx.triggered_id, e),
                type="error",
            )
        },
    )

app = dash.Dash(__name__, on_error=handle_global_error)

  应用页面内容代码如下,我们定义了两组按钮及对应的输出目标:

app.layout = html.Div(
    [
        # 错误消息统一更新目标
        fac.Fragment(id="error-message"),
        fac.AntdSpace(
            [
                fac.AntdSpace(
                    [
                        fac.AntdButton("全局错误示例1", id="trigger-global-error1"),
                        fac.AntdText(id="trigger-global-error-output1"),
                    ]
                ),
                fac.AntdSpace(
                    [
                        fac.AntdButton("全局错误示例2", id="trigger-global-error2"),
                        fac.AntdText(id="trigger-global-error-output2"),
                    ]
                ),
            ],
            direction="vertical",
            style=style(width="100%"),
        ),
    ],
    style=style(padding=100),
)

  回调函数部分,我们则针对两组不同的“输入-输出”关系,分别在按钮累计点击次数nClicks偶数时,抛出不同的错误:

@app.callback(
    Output("trigger-global-error-output1", "children"),
    Input("trigger-global-error1", "nClicks"),
    prevent_initial_call=True,
)
def global_error_demo1(nClicks):
    """示例回调函数1"""
    if nClicks % 2 == 0:
        # 触发示例错误
        1 / 0

    return f"nClicks: {nClicks}"


@app.callback(
    Output("trigger-global-error-output2", "children"),
    Input("trigger-global-error2", "nClicks"),
    prevent_initial_call=True,
)
def global_error_demo2(nClicks):
    """示例回调函数2"""
    if nClicks % 2 == 0:
        # 触发示例错误
        raise Exception("这是一个自定义错误")

    return f"nClicks: {nClicks}"

  应用操作演示如下,可以看到所有的错误都被全局错误处理函数捕获并进行集中处理😉:

1.2 局部错误处理

  与上文中介绍的全局错误处理写法不同,当我们希望将自定义的错误处理函数专门作用于某个或某些回调函数时,可以在对应回调函数的app.callback()中将自定义函数赋值给同名的on_error参数,我们在前面示例的基础上进行改造(对应本文源码app2.py),额外定义了错误处理函数handle_local_error,并赋值给对应回调函数的on_error参数,对应代码片段如下:

def handle_local_error(e):
    # 利用服务端set_props()将错误信息集中抛出
    set_props(
        "error-message",
        {
            "children": fac.AntdMessage(
                content="🧐异常发生,异常信息 {}".format(e),
                type="error",
            )
        },
    )


@app.callback(
    Output("trigger-global-error-output2", "children"),
    Input("trigger-global-error2", "nClicks"),
    on_error=handle_local_error,
    prevent_initial_call=True,
)
def global_error_demo2(nClicks):
    """示例回调函数2"""
    if nClicks % 2 == 0:
        # 触发示例错误
        raise Exception("这是一个自定义错误")

    return f"nClicks: {nClicks}"

  应用操作效果如下,可以看到通过设置on_error=handle_local_error,我们成功的改变了回调函数global_error_demo2的错误处理过程:

  大家可以在日常Dash应用开发的过程中,妥善使用这套机制,使得我们的应用功能更稳健😎~

2 浏览器端回调上下文补充outputs_list

  新版本为浏览器端回调函数中可以调用的上下文对象window.dash_clientside.callback_context补充了outputs_list属性,可以在一些特殊的场景下,在计算逻辑中取得此属性辅助计算。

  举个简单的例子,下面我们构造了10组开关输入框,每个开关的勾选可以控制对应输入框的禁用状态,且同时最多禁用3组,操作演示效果如下:

  具体回调逻辑见文章开头地址中的源码app3.py,借助上下文中的outputs_list,实现了更具针对性的高效回调更新。

  除此之外,还针对动态回调函数增加了动态依赖库加载等新特性,并修复了若干小问题,完整的更新内容说明请移步https://github.com/plotly/dash/releases/tag/v2.18.0


  以上就是本文的全部内容,对Dash应用开发感兴趣的朋友,欢迎添加微信号CNFeffery,备注“dash学习”加入我们的技术交流群,一起成长一起进步。

posted @ 2024-09-05 15:07  费弗里  阅读(236)  评论(0编辑  收藏  举报