I’m learning python and dash and I’m building an application for monitoring my trading.
I’ve adapted the code from : “Live Updating Components” example (Orbital Satellite). It works well on jupyter notebook and repl.it but I have an error when I try it on my computer :
"Traceback (most recent call last):
File "orbital.py", line 62, in
Input('interval-component', 'n_intervals'))"
“The input argument interval-component.n_intervals must be a list or tuple of
dash.dependencies.Inputs.”
I don’t understand why
Here is my code :
import ccxt
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly
from dash.dependencies import Input, Output
import pandas as pd
app = dash.Dash(__name__)
ftx = ccxt.ftx({'verbose': True})
ftx = ccxt.ftx({
'apiKey': '',
'secret': '',
})
app.layout = html.Div(
html.Div([
html.H4('FTX Live Feed'),
html.Div(id='live-update-text'),
dcc.Interval(
id='interval-component',
interval=1*1000, # in milliseconds
n_intervals=0
)
])
)
class Client:
"""A sample client class"""
def __init__(self):
self.pnl = []
#classmethod
def get_balances(client):
try:
balance = ftx.fetch_balance()
except ccxt.BaseError as e:
print(f"Could not get account with error: {e}")
raise e
else:
result = balance["info"]["result"]
total = []
for x in result:
if float(x["free"]) > 0.0:
total.append(x["usdValue"])
a = list(map(float, total))
df = pd.Series(a)
# global totCap
totCap = df.sum()
return totCap
#app.callback(Output('live-update-text', 'children'),
Input('interval-component', 'n_intervals'))
def update_metrics(n):
arc = Client().get_balances()
style = {'padding': '5px', 'fontSize': '16px'}
return [
html.Span('Balance: {0:.2f}'.format(arc), style=style)
]
if __name__ == '__main__':
app.run_server(host="0.0.0.0", port="8050")
Here is a screenshot from the replit app :
replit dash
As the error is trying to say, you need to wrap your Input in a list, like this:
#app.callback(Output('live-update-text', 'children'),
[Input('interval-component', 'n_intervals')])
Related
I've been trying to make a live graph with dash. This is my first time trying out dash but I've come across a problem. I write the callback functions to update the graph according to the update intervals. But even though the function is called(which I verify by adding print statements), the graph itself doesn't update.
import os
import dash
from dash import dcc, html
import pandas as pd
import os
from dotenv import load_dotenv
from sqlalchemy import create_engine
import plotly.graph_objs as go
from dash.dependencies import Input, Output
load_dotenv()
purl = os.environ.get('url')
dbname = 'database'
engine = create_engine(purl + dbname)
table_name = 'SANDBTC'
df = pd.read_sql(table_name.lower(), engine)
print(df)
app_name = 'dash-plots'
def _create_fig():
df = pd.read_sql(table_name.lower(), engine)
print(df)
return go.Figure(
data=go.Scatter(
x=df['Time'],
y=df['result']))
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.title = 'Graphs'
app.layout = html.Div(children=[html.H1(id='live-text', style={'textAlign': 'center'}),
dcc.Graph(
id='dash-graph',
animate=True,
figure=_create_fig()
),
dcc.Interval(
id='interval-component',
interval=1000,
n_intervals=0
)
], className="container")
#app.callback(Output('live-text', 'children'),
[Input('interval-component', 'n_intervals')])
def update_text(n):
return html.Span(f'No of times updated: {n}')
#app.callback(Output('dash-graph', 'figure'),
[Input('interval-component', 'n_intervals')])
def update_graph(n):
return _create_fig()
if __name__ == '__main__':
app.run_server(debug=True)
The update text function is working fine but for some reason the update graph function doesnt work. Can anyone point out what error im doing.Thank you for your help.
I removed animate=true and it works
I have an app with multiple pages, controlled from this index, in a new page I want to insert a dash table and assign some interactivity using callbacks. Take a basic dash table example (https://dash.plotly.com/datatable) and insert it into my app, but the callback doesn't get executed. The only thing that changes when inserting into my app, is the way I create the app.layout, which is created from a function.
The table is created but the callback doesn't trigger.
Index.py
import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
from homepage import Homepage
from resumen_comunal import Resumen_Comunal
from dash_main_table import main_Table
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.FLATLY])
app.config.suppress_callback_exceptions = True
app.layout = html.Div([
dcc.Location(id = 'url', refresh = False),
html.Div(id = 'page-content')
])
#app.callback(dash.dependencies.Output('page-content', 'children'),
[dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
if pathname == '/Cobertura_CV':
return Resumen_Comunal()
if pathname == '/Gestion_CV':
return main_Table()
else:
return Homepage()
if __name__ == '__main__':
app.run_server(debug=False)
dash_table.py
import dash
from dash import Dash, dash_table, dcc, html
from dash.dependencies import Input, Output
import pandas as pd
import dash_bootstrap_components as dbc
from navbar import Navbar
nav = Navbar()
app = dash.Dash(__name__, external_stylesheets = [dbc.themes.FLATLY])
df = pd.read_csv('https://git.io/Juf1t')
body = dbc.Container([
dbc.Label('Click a cell in the table:'),
dash_table.DataTable(df.to_dict('records'),[{"name": i, "id": i} for i in df.columns], id='tbl'),
dbc.Alert(id='tbl_out'),
])
#app.callback(Output('tbl_out', 'children'),
Input('tbl', 'active_cell'))
def update_graphs(active_cell):
return str(active_cell) if active_cell else "Click the table"
def main_Table():
layout = html.Div([
nav,
body
])
return layout
if __name__ == "__main__":
app.run_server(debug=True)
Thanks for your help!
So, the callback is not triggered because you’re trying to populate the dash table in a separate application while the callback for the same is created inside a different application.
You don't have to create a new app object given that it's already created in index.py and the layout is passed to that same app object
Here's what you should do inside dash_table.py
import dash
from dash import Dash, dash_table, dcc, html,callback
from dash.dependencies import Input, Output
import pandas as pd
import dash_bootstrap_components as dbc
from navbar import Navbar
nav = Navbar()
df = pd.read_csv('https://git.io/Juf1t')
body = dbc.Container([
dbc.Label('Click a cell in the table:'),
dash_table.DataTable(df.to_dict('records'),[{"name": i, "id": i} for i in df.columns], id='tbl'),
dbc.Alert(id='tbl_out'),
])
#callback(Output('tbl_out', 'children'),
Input('tbl', 'active_cell'))
def update_graphs(active_cell):
print(active_cell)
return str(active_cell) if active_cell else "Click the table"
def main_Table():
layout = html.Div([
nav,
body
])
return layout
I'm new in Dash. I'm trying to use a daq.BooleanSwitch() like an input to callback a graph. I can display a message but I have troubles with the graph.
Does anyone have any advice that can help me?
import dash
from dash.dependencies import Input, Output
import dash_daq as daq
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div([
html.H1("Here we go"),
daq.BooleanSwitch(id='my_pb', on=False,color="red"),
html.Div(id='power-button-result-1'),
dcc.Graph(id="plot")
])
#app.callback(
Output('power-button-result-1', 'children'),
Input('my_pb', 'on')
)
def update_output(on):
x = '{}'.format(on)
if x == "True":
return "Hi Iḿ using DASH"
#app.callback(
Output('plot', 'figure'),
Input('my_pb', 'on')
)
def figura(on):
x = '{}'.format(on)
if x == "True":
# fig1 = Code to do a nice plot
return fig1
if __name__ == "__main__":
app.run_server(port = 1895)
My DASH output look like this:
I took a look at your code, and a couple changes were necessary:
import dash
import dash_daq as daq
from dash import dcc
from dash import html
from dash.dependencies import Input
from dash.dependencies import Output
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.H1("Here we go"),
daq.BooleanSwitch(id="my_pb", on=False, color="red"),
html.Div(id="power-button-result-1"),
]
)
#app.callback(
Output("power-button-result-1", "children"),
Input("my_pb", "on"),
)
def update_output(on):
x = "{}".format(on)
if x == "True":
return [dcc.Graph(id="plot")]
if __name__ == "__main__":
app.run_server(debug=True)
You were super close - I think you only need one callback. Here, you can see the boolean switch now toggles the display (or not) of the dcc.Graph object. Is this what you were looking for?
↓ (toggle the switch)
If you want the graph to already be displayed, and then updated upon toggling, here's a slightly modified expanded version of same code above to do that:
import dash
import dash_daq as daq
from dash import dcc
from dash import html
from dash import no_update
from dash.dependencies import Input
from dash.dependencies import Output
import plotly.express as px
import pandas as pd
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.H1("Here we go"),
daq.BooleanSwitch(id="my_pb", on=False, color="red"),
html.Div(
[dcc.Graph(id="plot")], id="power-button-result-1"
),
]
)
#app.callback(
Output("power-button-result-1", "children"),
Input("my_pb", "on"),
)
def update_output(on):
df = px.data.iris()
if on:
fig = px.scatter(df, x="sepal_width", y="sepal_length")
dcc.Graph(figure=fig)
return [dcc.Graph(figure=fig)]
else:
fig = px.scatter()
return [dcc.Graph(figure=fig)]
if __name__ == "__main__":
app.run_server(debug=True)
There - that's much better, hopefully helpful?
When I run the code i get the graph but the graph is not getting updated i am calling the data from my sql laptop sql management studio.
Kindly let me know what needs to be done the X axis contains date and time and Y axis contains data in numeric form which is getting updated automatically
Code:
import pandas as pd
import pyodbc
import numpy as np
server ='LAPTOP-OO3V36UA\SQLEXPRESS'
db='addy'
conn=pyodbc.connect('DRIVER={SQL Server}; SERVER=' +server + ';DATABASE=' + db +
';Trusted_connection=yes')
sql="""
SELECT * FROM Summry
"""
df=pd.read_sql(sql ,conn)
import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html
from random import random
import plotly
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(id='live-update-graph-scatter', animate=True),
dcc.Interval(
id='interval-component',
interval=1*1000
)
])
#app.callback(Output('live-update-graph-scatter', 'figure'),
[Input('interval-component', 'interval')])
def update_graph_scatter():
df=pd.read_sql(sql ,conn)
trace1=go.Scatter(
y=df['ACL'],
x = df['DateandnTime'],
mode='lines',
name='ACL'
)
layout = go.Layout(
title='Daily Monitoring'
)
return {'data': trace1, 'layout': layout}
if __name__ == '__main__':
app.run_server()
You've set your callback's input to
Input('interval-component', 'interval')
But you want
Input('interval-component', 'n_intervals')
The interval property sets how frequently n_intervals gets updated. The change in n_intervals is what can be used to trigger the callback.
Here's the documentation: https://dash.plotly.com/dash-core-components/interval
I would like to create a stopwatch using python plotly dash and the following is my code. Here I use the element dcc.Interval to update timing information every one second, but unfortunately, I found that it is not accurate when I used my iPhone built-in stopwatch to test its accuracy. Any suggestion on how how to correct my code? Thanks :)
# import modules
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
# define functions
def sec_transform(i):
m, s = divmod(i, 60)
msg = '%02i:%02i' % (m, s)
return msg
# dashboard layout
app = dash.Dash()
app.layout = html.Div([
# display time elapsed
html.H1(id='live-update-text'),
# for live updating
dcc.Interval(
id='interval-component',
interval=1000, # 1000 milliseconds
n_intervals=0
)
])
# call back function
#app.callback(Output('live-update-text', 'children'),
[Input('interval-component', 'n_intervals')])
def update_layout(n):
msg = sec_transform(n)
return msg
if __name__ == '__main__':
app.run_server()