App.run is rerunning the statements inside the if __name__ == '__main__' block

import sys
sys.path.append("C:\\Users\\explrorer\\Desktop\\PaytmAPIsTrading\\PaytmApiUtils")
sys.path.append("C:\\Users\\explrorer\\Desktop\\PaytmAPIsTrading")

import dash
from dash import Dash, html, dcc, Input, Output, callback
from websocketclient import setUpTokens, websocketOption
from optiondashboard_utils import getInstruments, getStrikeRanges, setUpWebsocketClients, updateStrikeRange
from datetime import date
import logging
import pandas as pd
from processQuotesSql import processLiveQuotes
import multiprocessing as mp

logging.basicConfig(level=logging.INFO)

def generateAppLayout(strike_range, option_expiry_dates):
    range_sliders_elements = []
    for expDate in option_expiry_dates:
        range_sliders_elements += [ html.P(f"Select Range of strikes to consider for Optio Expiry({expDate.strftime('%Y-%m-%d')}):"),
                                    dcc.RangeSlider(strike_range[expDate][0], strike_range[expDate][-1], 50, value=[strike_range[expDate][0], strike_range[expDate][-1]], id=f"my-range-slider-{expDate.strftime('%Y-%m-%d')}") ]

    input_attribute_callback = []
    for expDate in option_expiry_dates:
        input_attribute_callback.append( Input(f"my-range-slider-{expDate.strftime('%Y-%m-%d')}", 'value') )

    app = Dash(__name__)
    app.layout = html.Div([html.Div(children='Option Quotes Downloader'),] + range_sliders_elements +  [html.Div(id='output-container-range-slider')])

    return app, input_attribute_callback
    
if __name__ == '__main__':
    option_expiry_dates = [date(2024,1,11), date(2024,1,18), date(2024,1,25), date(2024,2,29), date(2024,3,28)]
    fut_expiries = [date(2024,1,25), date(2024,2,29), date(2024,3,28)]
    symbol = 'NIFTY'
    setUpTokens()
    strike_range = getStrikeRanges(option_expiry_dates)
    instruments_to_consider = getInstruments( option_expiry_dates, fut_expiries, strike_range)
    app, input_attribute_callback = generateAppLayout(strike_range, option_expiry_dates)

    write_q = mp.Queue()

    # starting this first so that the process is ready before websockets starts inserting the data into the mp.queue
    process_quotes_sql_process = mp.Process(target = processLiveQuotes, args = (write_q,))
    process_quotes_sql_process.start()

    websocketsForOptions, webSocketForFutsAndIdx, threadsForOptions, threadsForFutsAndIdx = setUpWebsocketClients(option_expiry_dates, fut_expiries, instruments_to_consider, write_q)
    
    @callback( Output('output-container-range-slider', 'children'), tuple(input_attribute_callback) )
    def update_strike_range(*args):
        out = ""
        for expDate, strike_range_expDate in zip(option_expiry_dates, args):
            if (( strike_range_expDate[0] != strike_range[expDate][0] ) or (strike_range_expDate[1] != strike_range[expDate][1])):
                # we need to update the strike range for this expiry date
                websocketsForOptions = updateStrikeRange(expDate, strike_range_expDate, websocketsForOptions, threadsForOptions, instruments_to_consider, strike_range, write_q)
                out += f"Updated Strike Range for Expiry({expDate.strftime('%Y-%m-%d')}) to ({strike_range_expDate[0]},{strike_range_expDate[1]})\n"
                
        return out
    
    print(f"I am {__name__} process")
    
    app.run(debug=True, port = 9000)

The print statement is appearing twice

I am main process
I am main process

where both of the times name = main. I thought that if app.run indeed spawns a parallel process, it will not execute the content inside of main block but that is not the case, what can be done here?

I am creating several websocket connections inside the main process itself and a separate process to execute the messages of those websockets and I don’t want to recreate those connections.

Hi @explrorer , try with debug=False

1 Like

Thanks man. It actually worked :slight_smile:

1 Like