The following app exhibits this behavior with dash==0.40.0
# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash_table import DataTable
from dash.dependencies import Input, Output, State
import pandas as pd
from datetime import date, datetime, timedelta
import time
url = 'https://github.com/plotly/datasets/raw/master/26k-consumer-complaints.csv'
rawDf = pd.read_csv(url)
df = rawDf.to_dict("rows"),
app = dash.Dash()
app.scripts.config.serve_locally = True
app.layout = html.Div(children=[
html.Button(
id='button-update',
children=['Update']
),
dcc.DatePickerRange(
id='my-date-picker-range',
min_date_allowed=date(2018, 12, 14),
max_date_allowed=date.today(),
start_date=date.today() - timedelta(days=7),
end_date=date.today(),
display_format='D/M/Y'
),
dcc.Loading(
id="loading-1",
children=[
DataTable(
id='datatable-weapons',
columns=[{"name": i, "id": i, "type": "numeric", 'format': {'locale': {'group': '.', 'decimal': ','}}} for i in rawDf.columns],
data=[]
)
]
)])
@app.callback(
[Output('my-date-picker-range', 'start_date'), Output('my-date-picker-range', 'end_date')],
[Input('button-update', 'n_clicks')])
def update_output(n_clicks):
if n_clicks is not None and n_clicks > 0:
start_date = date(2019, 2, 12)
end_date = date.today()
return start_date, end_date
return date(2019, 2, 23), date(2019, 2, 27)
@app.callback(
[Output('datatable-weapons', 'data')],
[Input('my-date-picker-range', 'start_date'), Input('my-date-picker-range', 'end_date')])
def update_graph(begin_dt, end_dt):
begin_date = datetime.strptime(begin_dt, '%Y-%m-%d')
end_date = datetime.strptime(end_dt, '%Y-%m-%d')
days = (end_date - begin_date).days
rawDfSlice = rawDf[0:days]
dfSlice = rawDfSlice.to_dict("rows")
time.sleep(5)
return (dfSlice,) # This value needs to be wrapped to be accepted by Dash
if __name__ == "__main__":
app.run_server(port=8053)
return (dfSlice,) above works, but normal usage return dfSlice causes this error:
[2019-03-27 09:58:18,898] ERROR in app: Exception on /_dash-update-component [POST]
Traceback (most recent call last):
File "/Users/marc-andrerivet/.pyenv/versions/release-py37/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/Users/marc-andrerivet/.pyenv/versions/release-py37/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/marc-andrerivet/.pyenv/versions/release-py37/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/marc-andrerivet/.pyenv/versions/release-py37/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/Users/marc-andrerivet/.pyenv/versions/release-py37/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/marc-andrerivet/.pyenv/versions/release-py37/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/marc-andrerivet/projects/release/dash/dash/dash.py", line 1073, in dispatch
response.set_data(self.callback_map[output]['callback'](*args))
File "/Users/marc-andrerivet/projects/release/dash/dash/dash.py", line 986, in add_context
len(output_value)
dash.exceptions.InvalidCallbackReturnValue: Invalid number of output values for ..datatable-weapons.data...
Expected 1 got 4
Returning a plain array also exhibits the problem:
return [{ 'prop1': 'value1'}, { 'prop1': 'value2 }]
Did I get this wrong somehow?
Suggested approach
One approach could be to not validate the size of the output tuple in cases where the callback returns a single output. This will provide an experience consistent with the previous versions of Dash, not introduce a breaking change in behavior, provide a consistent coding experience throughout all the props/callbacks, and not break the abstraction between Dash usage and implementation details on our side.
What this approach loses in validation "perfectness" is more than made up from noise reduction in real usage scenarios. In any case, prop validation can easily pick up the slack from this "incorrectness". Put another way, giving priority to external facing consistency vs. internal facing consistency.
Tagging @T4rk1n
After testing this further and discussing this with @T4rk1n and @alexcjohnson, I agree that this is neither a regression nor a bug. Closing. Will open another issue for multi-output allowing an empty array of outputs.
hi @Marc-Andre-Rivet,
i'v got similar error ,and also need to wrap the output in a tuple as return (out_array, )
can you share why this is not a bug and why have to write it this way?
If you wrap your output definition in an array:
@app.callback(
[Output('datatable-weapons', 'data')],
then you also have to wrap your return in an array / tuple:
return (dfSlice,)
If you don't wrap the output definition:
@app.callback(
Output('datatable-weapons', 'data'),
then you don't wrap your return:
return dfSlice
Most helpful comment
If you wrap your output definition in an array:
then you also have to wrap your return in an array / tuple:
If you don't wrap the output definition:
then you don't wrap your return: