Python 装饰器作为 Dash 中的回调使用作为实例变量的 Dash 对象 - 失败
Posted
技术标签:
【中文标题】Python 装饰器作为 Dash 中的回调使用作为实例变量的 Dash 对象 - 失败【英文标题】:Python Decorator as Callback in Dash Using Dash Object That is an Instance Variable - Fails 【发布时间】: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' 未定义
是否有一种简单的方法来设置此装饰器以使其工作,同时仍将我的代码保留在类定义中?我猜装饰器正在进行一些预处理,但我不太了解它,无法提出解决方案。
【问题讨论】:
【参考方案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
【讨论】:
以上是关于Python 装饰器作为 Dash 中的回调使用作为实例变量的 Dash 对象 - 失败的主要内容,如果未能解决你的问题,请参考以下文章
Plotly Dash:选择 DataTable 中的行作为回调输出 + 过滤器
在 Dash (python) 中,我遇到了滑块和 radioitem 回调的问题