【问题标题】:Python Decorator as Callback in Dash Using Dash Object That is an Instance Variable - FailsPython 装饰器作为 Dash 中的回调使用作为实例变量的 Dash 对象 - 失败
【发布时间】:2019-07-10 18:56:46
【问题描述】:

我正在更新一些代码以使用 Dash 和 plotly。绘图的主要代码是在一个类中定义的。我用 Dash 控件替换了一些 Bokeh 小部件,最后得到了一个如下所示的回调:

class MakeStuff:
    def __init__(self, ..., **optional):
        ...
        self.app = dash.Dash(...)
        ...

    @self.app.callback(
    dash.dependencies.Output('indicator-graphic', 'figure'),
        [dash.dependencies.Input('start-time-slider', 'value'),
         dash.dependencies.Input('graph-width-slider', 'value')]
        )
    def update_graphs(self,range_start,graph_width):
        print(...)

我正在关注Dash website 中的一些示例。我能够运行示例,包括回调。在我的代码中,没有装饰器,代码运行没有错误,产生了我期望的图形和控件。 (当然,代码不完整,但没有错误。)当我包含装饰器时,我得到这个错误:

NameError: name 'self' 未定义

我是这样累的,首先,只是模仿代码示例:

class MakeStuff:
    def __init__(self, ..., **optional):
        ...
        app = dash.Dash(...)
        ...

    @app.callback(
    dash.dependencies.Output('indicator-graphic', 'figure'),
    [dash.dependencies.Input('start-time-slider', 'value'),
     dash.dependencies.Input('graph-width-slider', 'value')]
    )
    def update_graphs(self,range_start,graph_width):
        print(...)

当然,变量“app”只能在init函数的范围内知道,所以它不起作用也就不足为奇了,给出类似的错误:

NameError: name 'app' 未定义

是否有一种简单的方法来设置此装饰器以使其工作,同时仍将我的代码保留在类定义中?我猜装饰器正在进行一些预处理,但我不太了解它,无法提出解决方案。

【问题讨论】:

    标签: python callback python-decorators plotly-dash


    【解决方案1】:

    您可以不将回调函数作为装饰器调用,如this answer 所示。这应该在您的 __init__ 函数中起作用:

    class MakeStuff:
        def __init__(self, ..., **optional):
            ...
            self.app = dash.Dash(...)
            self.app.callback(
                dash.dependencies.Output('indicator-graphic', 'figure'),
                [dash.dependencies.Input('start-time-slider', 'value'),
                 dash.dependencies.Input('graph-width-slider', 'value')]
                )(self.update_graphs)
            ...
    
        def update_graphs(self,range_start,graph_width):
            print(...)
    

    我以前从未尝试过使用类实例,但看不出有什么理由不工作。

    【讨论】:

      【解决方案2】:

      ned2 提供了一个解决方案here,他使用以下结构在类定义中设置装饰器。

      class BaseBlock:
      def __init__(self, app=None):
          self.app = app
      
          if self.app is not None and hasattr(self, 'callbacks'):
              self.callbacks(self.app)
      
      class MyBlock(BaseBlock):
          layout = html.Div('layout for this "block".')
      
          def callbacks(self, app):
      
              @app.callback(Output('foo', 'figure'), [Input('bar')])
              def do_things(bar):
                  return SOME_DATA
      
              @app.callback(Output('baz', 'figure'), [Input('boop')])
              def do_things(boop):
                  return OTHER_DATA
      
      # creating a new MyBlock will register all callbacks
      block = MyBlock(app=app)
      
      # now insert this component into the app's layout 
      app.layout['slot'] = block.layout
      

      【讨论】:

        猜你喜欢
        • 2021-09-10
        • 2020-10-10
        • 1970-01-01
        • 2010-11-16
        • 1970-01-01
        • 2021-08-08
        • 1970-01-01
        • 2021-02-27
        • 2017-05-07
        相关资源
        最近更新 更多