I achieved this using @jimmybow recommendation, by using visdcc.Run_js. I use Dash to run a huge (~25k lines) physics code for tokamaks. This code has many scripts that are not directly accessible to the GUI class, and they all use python’s logging module to write to a log text file. Because some of these scripts run for a long time, the user needed to be able to see where the code is at in the run when accessing from a web browser. So I just put the logfile into an html5 textarea.
I have a dcc.Interval running every 5 seconds to read the log file and then put it into an dcc.Textarea. Every time this interval runs, I also call the visdcc.Run_js to send the textarea to the bottom of the scrollable area. I’v included some code below to help illustrate this, but keep in mind that this is not a complete example (my main DASH script is ~2200 lines long).
app.layout = html.Div(
id="big-app-container",
children=[
#===interval for updating logFile every 5 seconds
dcc.Interval(
id='intervalLog',
interval=5*1000, # in milliseconds
n_intervals=0
),
#===visdcc to run js
visdcc.Run_js(id = 'javascriptLog', run = ""),
#=== your other code
runCode()
],
)
Then in the dash app where I wanted the log file i put a callback that has the visdcc.Run_js as an output (obviously your classNames will be different)
def buildLogTab():
return html.Div(
id="logTab",
children=[
html.H4("Log File Updated Every 5 Seconds"),
dcc.Textarea(id="logData", value='Initializing...', className="logBox",
readOnly=True),
],
className="wideBoxDark"
)
@app.callback([Output('logData', 'value'),
Output('javascriptLog', 'run')],
[Input('intervalLog', 'n_intervals')])
def updateLogFile(n):
if n < 1:
raise PreventUpdate
with open(logFile, "r") as f:
content = f.read()
logCMD = '''
var textarea = document.getElementById('logData');
textarea.scrollTop = textarea.scrollHeight;
'''
return content, logCMD
Hope this helps someone else trying to do this. Full physics code is here: https://github.com/plasmapotential/HEAT