Notes on Using Curses with Python Asyncio
It came time for me to write my first curses application (needed a GUI with minimal infrastructure requirements), which needed asyncio capabilities. I wouldn’t have minded finding more information on the webs on how the two standard libraries interact.
Here’s what I eventually discovered after coding the app (with a bonus template to start your own python curses app).
It’s about Polling vs. Blocking I/O
The curses getch() call can operate in both a blocking and a non-blocking mode. Either will work in asyncio, with at least one caveat - if the blocking getch() is called in a separate thread via an asyncio executor, it will not return some events, notably KEY_RESIZE. A polling mechanism is therefore recommented, e.g.:
self.stdscr.nodelay(True) while not self.done: char = self.stdscr.getch() if char == ERR: await asyncio.sleep(0.1) elif char == KEY_RESIZE: self.make_display() else: self.handle_char(char)
See a working demo template at curses_demo.py