Search code examples
python-3.xmultithreadingtwistedwin32com

How to have my defined refresh function running in the background of my twisted server


I have a simple twisted TCP server running absolutely fine, it basically deals with database requests and displays the right things its just an echo client with a bunch of functions, the database that is being read also updates I have this refresh function to open the database and refresh it however if I add this to the message functions it'll take too long to respond as the refresh function takes around 6/7 seconds to complete, my initial idea was to have this function in a while loop and running constantly refreshing every 5/10 mins but after reading about the global interpreter lock its made me think that that isn't possible, any suggestions on how to run this function in the background of my code would be greatly appreciated

I've tried having it in a thread but it doesn't seem to run at all when I start the thread, I put it under the if name == 'main': function and no luck!

Here is my refresh function

def refreshit()
    Application = win32com.client.Dispatch("Excel.Application")
    Workbook = Application.Workbooks.open(database)
    Workbook.RefreshAll()
    Workbook.Save()
    Application.Quit()
    xlsx = pd.ExcelFile(database)
    global datess
    global refss
    df = pd.read_excel(xlsx, sheet_name='Sheet1')
    datess = df.groupby('documentDate')
    refss = df.groupby('reference')


class Echo(Protocol):
    global Picked_DFS
    Picked_DFS = None
    label = None
    global errors
    global picked
    errors = []
    picked = []
    def dataReceived(self, data):
        """
        As soon as any data is received, write it back.
        """
        response = self.handle_message(data)
        print('responding with this')
        print(response)
        self.transport.write(response)

def main():
    f = Factory()
    f.protocol = Echo
    reactor.listenTCP(8000, f)
    reactor.run()

if __name__ == '__main__':
    main()

I had tried this to no avail

if __name__ == '__main__':
    main()
    thread = Thread(target = refreshit())
    thread.start()
    thread.join()

Solution

  • You have an important error on this line:

    thread = Thread(target = refreshit())
    

    Though you have not included the definition of refreshit (perhaps a function to consider renaming), I assume refreshit is a function that performs your refresh.

    In this case, what you are doing here is calling refreshit and waiting for it to return a value. Then, the value it returns is used as the target of the Thread you create here. This is probably not what you meant. Instead:

    thread = Thread(target = refreshit)
    

    That is, refreshit itself is what you want the target of the thread to be.

    You also need to be sure to sequence your operations so that everything gets to run concurrently:

    if __name__ == '__main__':
        # Start your worker/background thread.
        thread = Thread(target = refreshit)
        thread.start()
        # Run Twisted
        main()
        # Cleanup/wait on your worker/background thread.
        thread.join()
    

    You may also just want to use Twisted's thread support instead of using the threading module directly (but this is not mandatory).

    if __name__ == '__main__':
        # Start your worker/background thread.
        thread = Thread(target = refreshit)
        thread.start()
        # Run Twisted
        main()
        # Cleanup/wait on your worker/background thread.
        thread.join()