'''Proof of concept for integrating asyncio and tk loops. Terry Jan Reedy Run with 'python -i' or from IDLE editor to keep tk window alive. This version simply calls tk root.update in run_forever. Without this, the tk window only appears after loop.stop, unless root.update() is put in callbacks instead. If there are no pending asyncio callbacks, self._run_once will block indefinitely in a .select(None) call, waiting for an I/O event. To ensure that all tk events and callbacks get timely attention, either the method should be over-riden or __init__ should start an asyncio callback loop. The details depend on whether the GUI or network IO should get priority attention. ''' import asyncio as ai import tkinter as tk import datetime import threading # On Windows, need proactor for subprocess functions EventLoop = ai.SelectorEventLoop # Following gets ai.SelectorEventLoop # EventLoop = type(ai.get_event_loop()) class TkEventLoop(EventLoop): def __init__(self, root): self.root = root super().__init__() def run_forever(self): # copy with 1 new line for proof of concept """Run until stop() is called.""" self._check_closed() if self.is_running(): raise RuntimeError('Event loop is running.') self._set_coroutine_wrapper(self._debug) self._thread_id = threading.get_ident() try: while True: self._run_once() # can block indefinitely self.root.update() # new line if self._stopping: break finally: self._stopping = False self._thread_id = None self._set_coroutine_wrapper(False) root = tk.Tk() loop = TkEventLoop(root) ai.set_event_loop(loop) # Combine 2 event loop examples from BaseEventLoop doc. hello = tk.Label(root) timel = tk.Label(root) hello.pack() timel.pack() def hello_world(loop): hello['text'] = 'Hello World' loop.call_soon(hello_world, loop) def display_date(end_time, loop): timel['text'] = datetime.datetime.now() if (loop.time() + 1.0) < end_time: loop.call_later(1, display_date, end_time, loop) else: loop.stop() end_time = loop.time() + 10.1 loop.call_soon(display_date, end_time, loop) # Blocking call interrupted by loop.stop() loop.run_forever()