1

Reason For Question

I'm trying to create a Tkinter GUI that is able to ping a server with WebSockets. As far as I understand WebSockets needs to be used in an asynchronous environment (so using asyncio). And this does not work well with Tkinter that already has its own event loop. So I found a solution that uses Tkinter's update(). And this has worked pretty well so far (I set the sleep time to 0.01 seconds and seems to work fine).

    async def gui_refresher(_root, _gui_sleep):
        """This is where the GUI's 'frames' will be updated and asyncio's event loop is 
           given a chance to preform actions. """

        # Run forever.
        while True:
            # Update the window.
            root.update()

            # Preform a context switch to check on other tasks for _gui_sleep's time.
            await asyncio.sleep(_gui_sleep)

In the rest of my application, I have 'send' and 'receive' task that uses a WebSocket to communicate with the server. And as I've said this works well.

Question

While this works, I have read that it is not advisable to use this update() method on the Tkinter window, since you will have nested event loops and in effect a memory leak. And here where the commenter says that you have to be careful with it, implying that it could work.

I have run my code for a few minutes looking at the memory usage doing all sorts of GUI calls and placing 200 widgets on my window. Nothing looked like a memory leak.

So my question is: when does a memory leak happen (or more precisely when does using update() lead to a nested event loop). And if gui_refresher() (in my code) is the only function that is using update() will that ever lead to a memory leak?

  • 1
    See [Update considered harmful](https://wiki.tcl-lang.org/page/Update+considered+harmful), an essay written by one of the people who probably wrote some of the `update` code. – Bryan Oakley Feb 01 '22 at 15:18
  • I've heard that using `update_idletasks()` is better, in case you wanted to know. – Sylvester Kruin Feb 01 '22 at 17:38
  • 1
    See the answer to this question for a method that allows tkinter and asyncio to work together but avoids calling update(): https://stackoverflow.com/questions/55464512/tkinter-and-asyncio-window-drag-resize-blocks-event-loop-single-thread – Paul Cornelius Feb 02 '22 at 04:08
  • Thank you @BryanOakley, I was looking for something like this. As far as I understand from the essay, as long as you only call `update()` as I did in the loop and not anywhere else you should be fine, but then the problem comes in that something like a `MessageBox` could also use `update()` and that's when you get nested event loops. – Dan de Vault Feb 02 '22 at 11:27
  • Thanks, @PaulCornelius, I used this and my program behaves exactly like my previous one did, except without the possibility of a nested event loop. – Dan de Vault Feb 02 '22 at 11:30
  • Any time you call `update` you run the risk of getting nested event loops, and nested event loops can cause problems that are hard to detect. – Bryan Oakley Feb 02 '22 at 16:43

0 Answers0