How to bind async method to a keystroke in Tkinter? How to bind async method to a keystroke in Tkinter? tkinter tkinter

How to bind async method to a keystroke in Tkinter?


tkinter itself is asynchronous thanks to event loop, the after method and the bindings.

However, if you trying to stick with asyncio it's also possible, but first let's consider what you tried.

Your first try is obviously a fail, because you trying to call spam as a generic function, when it's a coroutine. Your other tries are more correct than a first, but await coroutine or yield from coroutine can be used to start a coroutine from another coroutine only, so it fails again.

So the proper way of start that beast is a scheduling of its execution with a self-explanatory method ensure_future (or old async, which is just a deprecated alias).

Try this example:

import asyncioimport tkinter as tkclass App(tk.Tk):    def __init__(self):        super().__init__()        self._configure_bindings()    def _configure_bindings(self):        self.bind('<F5>', lambda event: asyncio.ensure_future(self.spam(event)))    async def spam(self, event):        await self.do_something()        await asyncio.sleep(2)        print('%s executed!' % self.spam.__name__)    async def do_something(self):        print('%s executed!' % self.do_something.__name__)async def run_tk(root):    try:        while True:            root.update()            await asyncio.sleep(.01)    except tk.TclError as e:        if "application has been destroyed" not in e.args[0]:            raiseif __name__ == '__main__':    app = App()    asyncio.get_event_loop().run_until_complete(run_tk(app))

Also, I think that it's worth to mention this question, since you use an update method.