I have an app which takes as input a Bloomberg ticker and outputs lots of different data (which are generated by querying Bloomberg direct using blpapi). One of the outputs is a dash table, which should show the relative performance of related securities over the years. I have encountered problems with the app because pretty much all of the functions/callbacks take a single input (the Bloomberg ticker) and they all fire simultaneously, causing the app to crash. Similarly, when the app is first loaded the callbacks are fired without an actual ticker in the input field, which creates nonsensical results from the Bloomberg calls - this also causes the app to periodically crash. To improve stability I therefore added time.sleep(x) elements to stagger each callback and some logic to suppress the initial firing of each callbacks, e.g.:
@app.callback(
Output(component_id='whatever_output', component_property='data'),
[Input(component_id='ticker', component_property='value')])
def function(ticker):
if ticker is None:
pass
else:
x = doWhatever(ticker)
return x
This logic to suppress the initial callback works fine except for the callback which generates data for a dash tableā¦after much pain Iāve found that after initially declaring the input as None and after including the aforementioned logic in the function, no matter what the value of the input the app skips over the function (Iām assuming it continues to think the value is None, even though it is definitely changing, and passes after the first logic statement).
So to elaborate, the following code works as expected:
- the value of āsecurityā is initially None
- but after loading the app the functions are all fired
- because I havenāt had a chance to change the input box, the data in the table is immediately set to ādata_AfterFiringā
- equally, if I change the input field to āTEST TICKERā the data in the table is set to ādata_TESTTICKERā
import dash
import dash_table
import dash_table.FormatTemplate as FormatTemplate
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
securityComment = html.P('security', style={'fontSize':'20px', 'textAlign':'right'})
securityInput = dcc.Input(id='security', type='text', debounce=True,
placeholder='ticker', value=None,
style={'fontSize':'20px', 'width': '200px'})
data_Initial = [{'ticker':'Initial Equity', 'ccy': 'EUR', '2013': 0.05, 'average': 0.05}]
data_AfterFiring = [{'ticker':'App has fired and removed the intialised data', 'ccy': 'EUR', '2013': 0.10, 'average': 0.10}]
data_TESTTICKER = [{'ticker':'UPDATED TICKER', 'ccy': 'JPY', '2013': 0.2, 'average': 0.2}]
forwardTable = dash_table.DataTable(id='forwardTable',
columns=[
{'name':'ticker', 'id':'ticker'},
{'name':'ccy', 'id':'ccy'},
{'name':'2013', 'id': '2013', 'type': 'numeric', 'format': FormatTemplate.percentage(2)},
{'name':'average', 'id': 'average', 'type': 'numeric', 'format': FormatTemplate.percentage(2)}],
filter_action='native',
sort_action='native',
style_header={'fontSize':'12px'},
style_data={'fontSize':'12px'},
data=data_Initial)
security = html.Div(
[
dbc.Row(
[
dbc.Col(securityComment, width=1),
dbc.Col(securityInput, width=1)
]
)
]
)
forwardAnalysis = html.Div(
[
dbc.Col(forwardTable, width=12)
]
)
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([security,
@app.callback(
Output(component_id='forwardTable', component_property='data'),
[Input(component_id='security', component_property='value')])
def fundForwardAnalysis(security):
if security == 'TEST TICKER':
return data_TESTTICKER
else:
return data_AfterFiring
if __name__ == '__main__':
app.run_server(debug=False)
However, now when I add the logic to suppress the initial firing I get the following behavior:
- the app loads and correctly reads that security == None, therefore the ādata_Initialā continues to display
- but no matter what value the security ticker takes afterwards, nothing is updatedā¦
@app.callback(
Output(component_id='forwardTable', component_property='data'),
[Input(component_id='security', component_property='value')])
def fundForwardAnalysis(security):
if security is None:
pass
elif security == 'TEST TICKER':
return data_TESTTICKER
else:
return data_AfterFiring
if __name__ == '__main__':
app.run_server(debug=False)
I have ten other callbacks where the initial firing is suppressed with this simple logic and they all work fine after the value of āsecurityā is changed to a proper tickerā¦I have no idea what is going on here. Equally, I have to suppress this particular initial callback because this function is responsible for 99% of the crashes (as in, when I comment this one out of my code the app is significantly more stableā¦).
Any comments, suggestions would be most welcomeā¦
Thanks