callback - 使用 plotly express 并在一页上有多个图形时,随机出现导入错误

标签 callback plotly importerror plotly-dash circular-dependency

Dash 相对较新,这是一个困扰我几个月的问题。我正在制作一个多页面应用程序,它使用卡片和嵌入在卡体中的图表显示一些基本数据趋势。在 30% 的情况下,应用程序运行良好,没有任何错误,而在另外 70% 的情况下,它会抛出以下任一错误:

  1. ImportError:无法从部分初始化的模块“plotly.validator_cache”导入名称“ValidatorCache”(很可能是由于循环导入) 或者
  2. ImportError:无法从部分初始化的模块“plotly.graph_objects”中导入名称“Layout”(很可能是由于循环导入)

这两种情况都是随机出现的,我通常会刷新应用程序以使它们消失。但显然我做错了什么。我有一组触发图形回调的下拉菜单。我一直在为这事绞尽脑汁。任何帮助/线索将不胜感激。我在错误中看到的唯一模式是,当在回调中调用 plotly express graphs 时,它们似乎会出现。

我做错了什么?我在网上到处搜索寻求帮助,但一无所获。

分享一些相关的代码片段(这可能太长而且很多部分对问题不重要,但可以让您大致了解我一直在努力的方向)

import dash
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
from plotly.subplots import make_subplots
import plotly.express as px


card_content1_1 = [
    dbc.CardHeader([dbc.Row([html.H5("SALES VOLUME TREND", className = "font-weight-bold text-success"),
                   dbc.Button(
                       html.I(className="fa fa-window-maximize"),
                       color="success",
                       id="sales_maximize",
                       className="ml-auto",
                       # href="www.cogitaas.com"
                   )
                             ])]),
     dbc.CardBody(
        [dcc.Graph(
    id='sales_graph',
    figure={},
            style={'height':'30vh'}
    # className="mt-5"
            )])]


card_stacked_discount = [
    dbc.CardHeader([dbc.Row([html.H5("VOLUMES UNDER DIFFERENT DISCOUNT LEVELS", className="font-weight-bold text-info text-center"),
                   dbc.Button(
                       html.I(className="fa fa-window-maximize"),
                       color="info",
                       id="discount_maximize",
                       className="ml-auto",
                       # href="www.cogitaas.com"
                   )
                             ])]),
    dbc.CardBody(
        [dcc.Dropdown(
                id = 'stacked_discount_dropdown',
                options =stacked_discount_options,
                value=stacked_discount_options[0].get('value'),
                style={'color':'black'},
                # multi=True
            ),
            dcc.Graph(
    id='stacked_discount_graph',
    figure={},
style={'height':'30vh'}
            )])]
cards = html.Div(
        [
            dbc.Row(
                [
                    dbc.Col(dbc.Card(card_content1_1, color="success", outline=True,
                                     style={'height':'auto'}), width=8),


                ],
                className="mb-4",

            ),

            dbc.Row(
                [
                    dbc.Col(dbc.Card(card_stacked_discount, color="info", outline=True), width=8),
                    dbc.Col(dbc.Card([
                        dbc.Row([
                            dbc.Col(dbc.Card(disc_sub_title, color="info", inverse=True)),
                        ]),
                        html.Br(),
                        dbc.Row([
                            dbc.Col(dbc.Card(disc_sub_card1, color="info", outline=True)),
                                              ]),
                    ]), width=4)
                ],
                className="mb-4",
            ),
        ]
    )

tab1_content = dbc.Card(
    dbc.CardBody(
        [cards,]
    ),
    className="mt-3",
)

tabs = dbc.Tabs(dbc.Tab(tab1_content, label="Data", label_style={'color':'blue'}, tab_style={"margin-left":"auto"}),])

content = html.Div([
        html.Div([tabs]),
        ],id="page-content")

app.layout = html.Div([dcc.Location(id="url"), content])


@app.callback(
    dash.dependencies.Output('sales_graph', 'figure'),
    [dash.dependencies.Input('platform-dropdown', 'value'),
     dash.dependencies.Input('signature-dropdown', 'value'),
     dash.dependencies.Input('franchise-dropdown', 'value'),
     dash.dependencies.Input('sales_maximize', 'n_clicks'),
     dash.dependencies.Input('time-dropdown', 'value'),
     ])
def update_sales_graph(plat, sign, fran, maximize, time_per):
    print(str(time_per)+"Test")
    time_ax=[]
    if isinstance(time_per,str):
        time_ax.append(time_per)
        time_per=time_ax
    if (time_per==None) or ('Full Period' in (time_per)):
        dff = df[(df.Platform==plat) & (df.Signature==sign) & (df.Franchise==fran)]
    elif ('YTD' in time_per):
        dff = df[(df.Platform == plat) & (df.Signature == sign) & (df.Franchise == fran) & (df.year==2020)]
    else:
        dff = df[(df.Platform==plat) & (df.Signature==sign) & (df.Franchise==fran) & (df.Qtr_yr.isin(time_per))]

    fig = px.area(dff, x='Date', y='Qty_Orig', color_discrete_sequence=px.colors.qualitative.Dark2)
    fig.add_trace(go.Scatter(x=dff['Date'], y=dff['Outliers'], mode = 'markers', name='Outliers',
                             line=dict(color='darkblue')))
    fig.add_trace(go.Scatter(x=dff['Date'], y=dff['bestfit'], name='Long Term Trend',
                             line=dict(color='darkblue')))
    fig.update_layout(font_family="Rockwell",
                      title={'text': fran + " Volume Trend",
                             'y': 0.99,
                             # 'x': 0.15,
                             # 'xanchor': 'auto',
                             'yanchor': 'top'
                             },
                      legend=dict(
                          orientation="h",
                          # y=-.15, yanchor="bottom", x=0.5, xanchor="center"
                      ),
                      yaxis_visible=False, yaxis_showticklabels=False,
                      xaxis_title=None,
                    margin=dict(l=0, r=0, t=0, b=0, pad=0),
                      plot_bgcolor='White',
                    paper_bgcolor='White',
                                          )
    fig.update_xaxes(showgrid=False, zeroline=True)
    fig.update_yaxes(showgrid=False, zeroline=True)
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
    if 'maximize' in changed_id:
        fig.show()
    return fig


@app.callback(
    dash.dependencies.Output('stacked_discount_graph', 'figure'),
    [dash.dependencies.Input('platform-dropdown', 'value'),
     dash.dependencies.Input('signature-dropdown', 'value'),
     dash.dependencies.Input('franchise-dropdown', 'value'),
     dash.dependencies.Input('discount_maximize', 'n_clicks'),
     dash.dependencies.Input('stacked_discount_dropdown', 'value'),
     dash.dependencies.Input('time-dropdown', 'value'),
     ])
def stacked_discount(plat, sign, fran, maximize, sales_days, time_per):
    time_ax=[]
    if isinstance(time_per,str):
        time_ax.append(time_per)
        time_per=time_ax
    # else:
    #     time_per=list(time_per)

    if (time_per==None) or ('Full Period' in (time_per)):
        df_promo = df_promo_vol[(df_promo_vol.Platform==plat) & (df_promo_vol.Signature==sign) & (df_promo_vol.Franchise==fran)]
    elif ('YTD' in time_per):
        df_promo = df_promo_vol[(df_promo_vol.Platform == plat) & (df_promo_vol.Signature == sign) & (df_promo_vol.Franchise == fran) & (df_promo_vol.Year==2020)]
    else:
        df_promo = df_promo_vol[(df_promo_vol.Platform==plat) & (df_promo_vol.Signature==sign) & (df_promo_vol.Franchise==fran) & (df_promo_vol.Qtr_yr.isin(time_per))]

    color_discrete_map = {
        "0 - 10": "orange",
        "10 - 15": "green",
        "15 - 20": "blue",
        "20 - 25": "goldenrod",
        "25 - 30": "magenta",
        "30 - 35": "red",
        "35 - 40": "aqua",
        "40 - 45": "violet",
        "45 - 50": "brown",
        "50 + ": "black"
    }

    category_orders = {'disc_range': ['0 - 10', '10 - 15', '15 - 20', '20 - 25', '25 - 30', '30 - 35', '35 - 40',
                                      '40 - 45', '45 - 50', '50 + ']}

    if (sales_days == None) or (sales_days == 'sales_act'):
        fig = px.bar(df_promo, x='start', y='units_shipped', color='disc_range',
                     color_discrete_map=color_discrete_map,
                     category_orders=category_orders,
                 )
    else:
        fig = px.bar(df_promo, x='start', y='Date', color="disc_range",
                    color_discrete_map=color_discrete_map,
                     category_orders=category_orders,
                     )

    fig.update_layout(font_family="Rockwell",
                      title={'text': fran + " Sales Decomposition",
                             'y': 0.99,
                             'x': 0.1,
                             # 'xanchor': 'auto',
                             'yanchor': 'top'
                             },
                      legend=dict(
                          orientation="h",
                          # y=-.15, yanchor="bottom", x=0.5, xanchor="center"
                      ),
                      # yaxis_visible=False, yaxis_showticklabels=False,
                      xaxis_title=None,
                      margin=dict(l=0, r=0, t=30, b=30, pad=0),
                      plot_bgcolor='White',
                      paper_bgcolor='White',
                      )
    fig.update_xaxes(showgrid=False, zeroline=True)
    fig.update_yaxes(showgrid=False, zeroline=True)
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
    if 'maximize' in changed_id:
        fig.show()
    return fig

最佳答案

好吧,看来我可能是无意中找到了答案。我在多个回调中使用了几乎相同的输入,这可能会对输入的顺序造成一些干扰。一旦我将代码集成到一个具有多个输出的回调中,问题似乎就消失了。

关于callback - 使用 plotly express 并在一页上有多个图形时,随机出现导入错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66149087/

相关文章:

javascript - 使用 CSS 绘制 Axis 位置

python - 为什么导入 ctypes 会引发 ImportError?

c - 如何将可变大小数组从 Windows 内核驱动程序传递到用户模式进程?

c# - 从 C++ 传递函数指针以供 C# 调用 - 函数的参数包括一个宽字符字符串 (LPCWSTR)

python - Jupyter Notebook 中未返回 Plotly 表

python - Plotly Python 中的刻度格式

c# - 创建类实例后回调函数结束(c#)

c# - 从 C# 调用 VC++ dll 中的回调函数

python - 从终端导入 python 文件

python - ImportError:没有名为 toripchanger 的模块,如何使用正确的 python 版本启动 scrapy