ImportError: cannot import name 'config' from 'plotly.io._json' - python

I am trying to make a basic Dash app, and I got this error. Here is my code.
import dash
import plotly
from dash import dcc
#from dash_core_components.Markdown import Markdown
from dash import html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import os
import PyPDF2
app = dash.Dash(__name__, meta_tags=[{"name": "viewport", "content": "width=device- width, initial-scale=1"}], external_stylesheets=[dbc.themes.SUPERHERO])
app.title = 'FODS'
server = app.server
app.layout = html.Div([
dcc.Input(
id='input_text',
type= 'text',
placeholder="Enter Unicode Search Phrase".format('text'),
),
html.Div(id = 'output-area')
])
#app.callback(
Output('output-area', 'children'),
Input('input_text', 'value'),
)
def return_pages(input_text):
locations = []
answers = 'Please refer '
for file in os.listdir('./Solutions'):
path = './Solutions/' + file
pdfFileObj = open(path, 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFileObj, strict = False)
for i in range(pdfReader.numPages):
pageObj = pdfReader.getPage(i)
text = str(pageObj.extractText())
if input_text in text:
locations.append([file, i+1])
answers += file + ', at page ' + str(i + 1) + ', '
if len(locations) != 0:
return answers + ' for your answers'
else:
return 'Sorry, your query fetched no answers'
if __name__ == '__main__':
app.run_server(debug=True)
Screenshot of the error on local development server
I have tried updating the libraries and restarting the venv. Please advise on what can be done. There is a slight time crunch on this project.
Thanks in advance.

Related

python plolty dash - read .pkl files and display them in plotly dash

i changed the following code from using ".png" to ".pkl". but this doesn't work
import plotly.express as px
import joblib
#generate example pkl
fig = px.scatter(x=range(10), y=range(10))
joblib.dump(fig, "img_dash/figure.pkl")
#%%
import dash
import dash_core_components as dcc
import dash_html_components as html
import flask
import glob
import os
image_directory = 'img_dash/'
list_of_images = [os.path.basename(x) for x in glob.glob('{}*.pkl'.format(image_directory))]
static_image_route = '/static/'
app = dash.Dash()
app.layout = html.Div([
dcc.Dropdown(
id='image-dropdown',
options=[{'label': i, 'value': i} for i in list_of_images],
value=list_of_images[0]
),
html.Img(id='image')
])
#app.callback(
dash.dependencies.Output('image', 'src'),
[dash.dependencies.Input('image-dropdown', 'value')])
def update_image_src(value):
return static_image_route + value
#app.server.route('{}<image_path>.pkl'.format(static_image_route))
def serve_image(image_path):
image_name = '{}.pkl'.format(image_path)
if image_name not in list_of_images:
raise Exception('"{}" is excluded from the allowed static files'.format(image_path))
return flask.send_from_directory(image_directory, image_name)
if __name__ == '__main__':
app.run_server(debug=False)
i expect to show the .pkl files in the dashboard with hover-function. may other formats also possible! i was not able to check this.
I recommend you to use a Graph component here instead of an Img component since you want to display these figures dynamically.
Since each pkl file already stores a Figure you can just dynamically load these files using joblib in your callback based on the dropdown value.
Example based on your code:
# Example figures for demo purposes
fig1 = px.scatter(x=range(10), y=range(10))
fig2 = px.scatter(x=range(15), y=range(15))
fig3 = px.scatter(x=range(20), y=range(20))
joblib.dump(fig1, "img_dash/figure1.pkl")
joblib.dump(fig2, "img_dash/figure2.pkl")
joblib.dump(fig3, "img_dash/figure3.pkl")
# ...
image_directory = "img_dash/"
list_of_images = [
os.path.basename(x) for x in glob.glob("{}*.pkl".format(image_directory))
]
app = dash.Dash()
app.layout = html.Div(
[
dcc.Dropdown(
id="image-dropdown",
options=[{"label": i, "value": i} for i in list_of_images],
value=list_of_images[0],
),
dcc.Graph(id="graph"),
]
)
#app.callback(
dash.dependencies.Output("graph", "figure"),
[dash.dependencies.Input("image-dropdown", "value")],
)
def update_graph(file):
return joblib.load(os.path.join(image_directory, file))
if __name__ == "__main__":
app.run_server(debug=False)

Dash Python interval error with live update

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')])

I want to create Python Dash app to watch a directory over ftp , extract data from the file and plot it in real time

I am working on a project on which I have to monitor a ftp directory for any new files which appear , once a new file appears I want to extract data from and plot the results in real time so far I have sorted out the ftp function that monitors the directory , for testing purpose I am using my phone as a test ftp server and I have created a function which uploads a new file every n seconds :
from ftplib import FTP
from time import sleep
import os
ftp = FTP()
ftp.connect('192.168.1.109', 2221)
ftp.login('android', 'android')
ftp.cwd('/test_folder')
folder = 'C:\\Users\\QC\\Desktop\\sample_files_to_upload'
for file in os.listdir(folder):
fp = open(folder + file,'rb')
ftp.storbinary('STOR %s' % os.path.basename(file), fp, 1024)
sleep(2)
fp.close()
sleep(2)
print("File {} uploaded sucessfully".format(file))
I also have a function which watches the directory for any new files which appear in the directory and as soon as the file appears it copies it on the local machine performs data extraction prints the output and removes the file:
from ftplib import FTP
from time import sleep
import time
import os
def monitor_ftp():
ftp = FTP()
ftp.connect('192.168.1.109', 2221', 21)
ftp.login('android', 'android)
ftp.cwd('/test_folder')
print("Connection Established {}".format(ftp.getwelcome()))
direct = 'C:\\Users\\QC\\Desktop\\local_temp_directory\\'
old_files = ['1']
#print(old_files)
while True:
try:
new_files = ftp.nlst()
#print(new_files)
#print(new_files)
if len(old_files) != 0 and new_files != old_files:
changes = [i for i in new_files if i not in old_files]
#
# print(changes)
for x in changes:
filename = str(direct + x)
localfile = open(filename, 'wb')
ftp.retrbinary('RETR'+' ' + x , localfile.write, 1024)
localfile.close()
xcorr = extract_function(filename)
print("updating data ***************************************************")
print("found new file---> {}".format(str(filename).split('\\')[-1]))
print("Calculating cross-correlation")
print("*****************************************************************")
print(" ")
sleep(3)
os.remove(filename)
a = time.perf_counter()
if time.perf_counter() > a + 20:
print("Done Waiting")
break
old_files = new_files
except KeyboardInterrupt:
ftp.quit()
I have also created a basic test_dash app :
import dash
import plotly.graph_objects as go
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc
from app import app
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Graph(id = 'live-graph', animate = True),
dcc.Interval(
id = 'graph-update',
interval = 10000,
n_intervals = 0
),
html.Div(dbc.Row([
dbc.Col(html.H2(id='check_update_div', children='check ' ))
]) )
]
)
#app.callback(
Output('check_update_div', 'children'),
[ Input('graph-update', 'n_intervals') ]
)
def update_graph_scatter(n):
print('one loop done ')
a = monitor_ftp()
return ("this is X {}".format(a))
I want to tie everything together and create a dash app which monitors the ftp directory and plots the result of data extract , currently I don't have a graph in my app, I have just put a div which I want to update with the file name for every new file that appears in the folder , but I am not sure how to combine these functions together. Can you please help.
Edit:
I have got a working example which shows that ftp inside the callback function prevents the function from returning anything , if ftp is outside the return function then callback returns and updates the div every n_intervals
import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html
import plotly
import random
import plotly.graph_objs as go
from collections import deque
from ftplib import FTP
from time import sleep
#ftp otside the function and function works fine
#Deactivae this part and activate ftp inside the function , and function
#stops returning anything and div is not updated every n_interval
ftp = FTP()
ftp.connect('10.199.44.240', 21)
ftp.login('display')
ftp.cwd('/home/display/test_qc')
print("Connection Established {}".format(ftp.getwelcome()))
direct = 'C:\\Users\\QC\\Desktop\\Gunlink_local\\'
app = dash.Dash(__name__)
app.layout = html.Div([
html.Div([
dcc.Interval(
id = 'graph-update',
interval = 10000,
n_intervals = 0
)
]),
html.Div([
html.H1(id='print_value', children="Output Value"),
])
])
#app.callback(
Output('print_value', 'children'),
[ Input('graph-update', 'n_intervals') ]
)
def update_value(n):
# ftp inside the function prevents the function from returning anything
# Div is not updated every n_interval
'''
ftp = FTP()
ftp.connect('10.199.44.240', 21)
ftp.login('display')
ftp.cwd('/home/display/test_qc')
print("Connection Established {}".format(ftp.getwelcome()))
a = ftp.nlst()
'''
a = ftp.nlst()
sleep(2)
print('one loop done ')
return ("this is X {}".format(a))
if __name__ == '__main__':
app.run_server()
You need the interval component.
Dash cannot do constant updates, like running that while loop nonstop, but you can have the interval set to fire a callback every X seconds. Using that callback, you can check the FTP server on that schedule for updates.
Check out this page of the docs for some good examples of using it to create a live-updating page.

How to subset and generate a large data frame with Python Dash?

I'm trying to create a Dash app that must:
Read a csv file and convert it to a dataframe
Subset this dataframe according to the user's choices (radio buttons,...)
Generate the subseted dataframe in a csv file
The issue is I can't subset the dataframe as I would like.
Let's imagine I got a data frame gas3 with a variable Flag. Here is a part of my code:
import dash
import dash_core_components as dcc # Graphs
import dash_html_components as html # Tags
from dash.dependencies import Input, Output, Event, State
from pandas_datareader import DataReader
import time
import pandas as pd
import plotly
import plotly.graph_objs as go
from collections import deque
import random
import os
import pandas as pd
import glob
import numpy as np
import statistics
from datetime import *
from pytz import *
import dash_table_experiments as dte
import io
from flask import send_file
import flask
import urllib.parse
# Import df
gas3 = pd.read_csv("D:/Path/gas3.csv", sep=';')
gas3['Date_Local_Time'] = pd.to_datetime(gas3['Date_Local_Time'], format='%Y/%m/%d %H:%M') # Conversion de la variable en type "date heure"
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets) # Starting application
app.layout = html.Div(children=[
# Radio buttons
html.Div([
html.Label("Sélectionnez la valeur du Flag que vous souhaitez :",
htmlFor='radioflag',
),
html.Br(),
html.Br(),
dcc.RadioItems(
id='radioflag',
options=[
{'label': 'Flag 0', 'value': 'Flag0'},
{'label': 'Flag 1', 'value': 'Flag1'},
{'label': 'Flag 3', 'value': 'Flag3'},
{'label': 'Chambre à flux', 'value': 'CAF'}
]
),
html.Br(),
]),
# Download button
html.Div(id='table'),
html.A(
'Download Data',
id='download-link',
download="rawdata.csv",
href="",
target="_blank"
)
])
### Subset function
def filter_data(flag):
gas_genere = gas3.copy()
if flag == 'Flag0':
gas_genere = gas_genere[gas_genere['Flag']==0]
return gas_genere
else:
return gas_genere[0:4]
# Callback
#app.callback(
Output('download-link', 'href'),
[Input('radioflag', 'value')])
def update_download_link(flag):
gas_genere = filter_data(flag)
csv_string = gas_genere.to_csv(index=False, encoding='utf-8', sep=';')
csv_string = "data:text/csv;charset=utf-8,%EF%BB%BF" + urllib.parse.quote(csv_string)
return csv_string
if __name__ == '__main__':
app.run_server(debug=True)
I found out the issue but I don't know how to fix it. If I change my filter_data function to (I just added [0:2] to the first return gas_genere) :
def filter_data(flag):
gas_genere = gas3.copy()
if flag == 'Flag0':
gas_genere = gas_genere[gas_genere['Flag']==0]
return gas_genere[0:2]
else:
return gas_genere[0:4]
The app works well! If I check "Flag 0", gas_genere[0:2] will be generated. Else, gas_genere[0:4] will be generated.
But if I keep it like in my original code, I can check "Flag 1", "Flag 3", "Chambre à flux" or don't check any button, it would work and generate gas_genere[0:4]. But if I check "Flag 0", instead of returning gas_genere, I would not get a csv file, but would get an error: "téléchargement Echec - Erreur réseau." which in English should be "Download Failed - Network Error".
I tryed to generate my dataframe gas_genere = gas3[gas3['Flag']==0] in Python and it got 14299 rows and 43 columns.
Is my dataframe too large? If so, what should I do?
Thank you!

Redirecting Python's console output to Dash

How can I redirect/show the console output (including outputs I print inside the program) so it would appear inside a Dash app (On the screen the user sees)?
I didn't find a way for Dash to read the console output directly, so I used a workaround using a text file.
Here is a sample code which prints the last 20 lines of the console output to an Iframe (as to keep the line breaks, which do not show in other text/div components):
import dash_core_components as dcc
import dash_html_components as html
import dash
import sys
f = open('out.txt', 'w')
f.close()
app = dash.Dash()
app.layout = html.Div([
dcc.Interval(id='interval1', interval=1 * 1000,
n_intervals=0),
dcc.Interval(id='interval2', interval=5 * 1000,
n_intervals=0),
html.H1(id='div-out', children=''),
html.Iframe(id='console-out',srcDoc='',style={'width':
'100%','height':400})
])
#app.callback(dash.dependencies.Output('div-out',
'children'),
[dash.dependencies.Input('interval1', 'n_intervals')])
def update_interval(n):
orig_stdout = sys.stdout
f = open('out.txt', 'a')
sys.stdout = f
print 'Intervals Passed: ' + str(n)
sys.stdout = orig_stdout
f.close()
return 'Intervals Passed: ' + str(n)
#app.callback(dash.dependencies.Output('console-out',
'srcDoc'),
[dash.dependencies.Input('interval2', 'n_intervals')])
def update_output(n):
file = open('out.txt', 'r')
data=''
lines = file.readlines()
if lines.__len__()<=20:
last_lines=lines
else:
last_lines = lines[-20:]
for line in last_lines:
data=data+line + '<BR>'
file.close()
return data
app.run_server(debug=False, port=8050)
Create a custom LoggerHandler, and use dcc.Interval for refreshing.
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import dash
import logging
class DashLoggerHandler(logging.StreamHandler):
def __init__(self):
logging.StreamHandler.__init__(self)
self.queue = []
def emit(self, record):
msg = self.format(record)
self.queue.append(msg)
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
dashLoggerHandler = DashLoggerHandler()
logger.addHandler(dashLoggerHandler)
app = dash.Dash()
app.layout = html.Div([
dcc.Interval(id='interval1', interval=5 * 1000, n_intervals=0),
html.H1(id='div-out', children='Log'),
html.Iframe(id='console-out',srcDoc='',style={'width': '100%','height':400})
])
#app.callback(
Output('console-out', 'srcDoc'),
Input('interval1', 'n_intervals'))
def update_output(n):
return ('\n'.join(dashLoggerHandler.queue)).replace('\n', '<BR>')
app.run_server(debug=False, port=8050)
One possible way to do this is supply it as input to Dash Core Component Text Area's value property. This should work if its a string.

Categories

Resources