How to start and pause file reading after clicking on start and pause button in dash

import dash
import dash_html_components as html
import dash_core_components as dcc
import readextdata
import os
import time
external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]

app = dash.Dash(name, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Div(dcc.Input(id=‘input-box’, type=‘text’)),
html.Button(‘Submit’, id=‘button’),
html.Button(‘Pause’, id=‘Pause’),
html.Button(‘Resume’, id=‘Resume’),
html.Div(id=‘output-container-button’,
children=‘Enter a value and press submit’)
])

@app.callback(
dash.dependencies.Output(‘output-container-button’, ‘children’),
[dash.dependencies.Input(‘button’, ‘n_clicks’),dash.dependencies.Input(‘Pause’, ‘n_clicks’),dash.dependencies.Input(‘Resume’, ‘n_clicks’)],
[dash.dependencies.State(‘input-box’, ‘value’),dash.dependencies.State(‘input-box’, ‘value’)])
def update_output(n_clicks1,n_clicks2,n_clicks3, value,value2):
global cur_line,cur_line_no,pos
print(n_clicks1)
fname = str(value)
fpath = os.path.join(os.getcwd(), fname)

if n_clicks1 >= 1:
    with open(fpath, 'r') as f:
        lines = f.readline()
        return dcc.Markdown(lines)

if name == ‘main’:
app.run_server(debug=True)

Please can you help me in this.

Firstly you need to make a choice as by default Dash doesn’t support appending data to props, so you can either:

  1. Read the whole file every time there is an update
  2. Or send the whole text between the server and the client and append on to the end of it

I’m going to give a simple example of 1. To make it a little more efficent I’m going to store the mtime of the file and only send an update when the mtime changes. For this you need to understand:

  1. dcc.Interval to refresh the page
  2. dcc.Store to store user side state rather than saving as a global variable
  3. Dash callback_context to figure out which button was pressed
  4. How to use multiple outputs

Here is the example of reading a file in the same directory as the script called “test.txt”:

# Standard Library
import os

# Third Party Libraries
import dash
import dash_html_components as html
import dash_core_components as dcc

current_directory = os.path.dirname(os.path.abspath(__file__))
file = os.path.join(current_directory, 'test.txt')
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
    html.Button('Pause', id='pause'),
    html.Button('Resume', id='resume'),
    html.Div(id='output-container-button',
             children='Enter a value and press submit'),
    dcc.Interval(id='refresh-interval', disabled=True, interval=1000),
    dcc.Store(id='mtime', storage_type='memory'),
    html.Pre(id='output'),
])

@app.callback(
    output=[dash.dependencies.Output('output', 'children'),
            dash.dependencies.Output('refresh-interval', 'disabled'),
            dash.dependencies.Output('mtime', 'data')],
    inputs=[dash.dependencies.Input('pause', 'n_clicks'),
            dash.dependencies.Input('resume', 'n_clicks'),
            dash.dependencies.Input('refresh-interval', 'n_intervals')],
    state=[dash.dependencies.State('mtime', 'data')]
)
def update_output(pause_n_clicks, resume_n_clicks, refresh_n_intervals, remote_mtime):
    if pause_n_clicks is None and resume_n_clicks is None:
        raise dash.exceptions.PreventUpdate

    # Get the prop triggering the callback so we know what to do
    triggered_prop = dash.callback_context.triggered[0]['prop_id']

    # Pause means no update to text, no update to mtime, and disable the refresh
    if triggered_prop == 'pause.n_clicks':
        return dash.no_update, True, dash.no_update

    # Resume or interval firing means check mtime and then read file
    if triggered_prop == 'resume.n_clicks' or triggered_prop == 'refresh-interval.n_intervals':

        # Get mtime of file and check if it's same as the one user already has
        local_mtime = os.path.getmtime(file)
        if local_mtime == remote_mtime:
            return dash.no_update, False, dash.no_update

        # Local and Remote mtime didn't match so send file contents
        return open(file, 'r').read(), False, local_mtime

    raise ValueError(f'Unknown prop: {triggered_prop}')

if __name__ == '__main__':
    app.run_server()
3 Likes

Thank You Damian.

But In my case I need to take input from textbox and then apply pause and resume functionality on given text file read operation. How can I implement this code on that case

Modify my example to add an input box, and if needed a submit button, add them to the callback arguments as appropriate and modify the callback logic to handle your what requirements you want.

My example is only intended to show you how to solve the fundamental features your asking for in Dash, not provide you with a complete app.

Got it. Thank You Damian