[Python-ideas] How the heck does async/await work in Python 3.5
Maxime S
maxischmeii at gmail.com
Fri Feb 26 17:12:16 EST 2016
2016-02-25 17:47 GMT+01:00 Guido van Rossum <guido at python.org>:
> When you're implementing this API on top of tkinter, you'll probably
> find that you'll have to use tkinter's way of sleeping anyways, so the
> implementation of waiting in BaseEventLoop using a selector is not
> useful for this scenario.
>
> There are probably some possible refactorings in the asyncio package
> to help you reuse a little more code, but all in all I still think it
> would be very useful to have an asyncio loop integrated with Tkinter.
> (Of course Tkinter does support network I/O, so it would be possible
> to integrate with that, too. Or some hybrid where you somehow figure
> out how to wait using a Selector *or* tkinter events in the same
> loop.)
>
It is actually quite easy to implement an asyncio loop over tkinter once
you realise that tkapp.dooneevent() is very similar to poll(), and
tkapp.createfilehandler() is very similar to register() (which is not that
surprising since tcl use poll() internally if available).
Thus it is possible to create a tk selector and reuse all the code in
SelectorEventLoop. Unfortunately createfilehandler() is only available on
UNIX, so some form of threading is probably innevitable on Windows.
class TkSelector(selectors._BaseSelectorImpl):
"""Selector based on the Tk event loop."""
def __init__(self, app):
super().__init__()
self.app = app
self.ready = []
self.is_timeout = False
self.after_key = None
def _file_cb(self, fileobj, mask):
fd = self._fileobj_lookup(fileobj)
self.ready.append((fd, mask))
def _timeout_cb(self):
self.is_timeout = True
def _reset_state(self):
del self.ready[:]
self.is_timeout = False
if self.after_key:
self.app.after_cancel(self.after_key)
self.after_key = None
def register(self, fileobj, events, data=None):
key = super().register(fileobj, events, data)
flags = 0
if events & EVENT_READ:
flags |= tkinter.READABLE
if events & EVENT_WRITE:
flags |= tkinter.WRITABLE
self.app.createfilehandler(fileobj, flags, self._file_cb)
return key
def unregister(self, fileobj):
key = super().unregister(fileobj)
self.app.deletefilehandler(fileobj)
return key
def select(self, timeout=None):
if timeout is None:
pass
elif timeout <= 0:
while self.app.dooneevent(_tkinter.DONT_WAIT):
pass
self.is_timeout = True
else:
self.after_key = self.app.after(math.ceil(timeout*1000),
self._timeout_cb)
while not (self.is_timeout or self.ready):
self.app.dooneevent()
ret = []
for fd, mask in self.ready:
events = 0
if mask & tkinter.WRITABLE:
events |= EVENT_WRITE
if mask & tkinter.READABLE:
events |= EVENT_READ
key = self._key_from_fd(fd)
if key:
ret.append((key, events & key.events))
self._reset_state()
return ret
class TkEventLoop(asyncio.SelectorEventLoop):
"""Asyncio-compatible tkinter event loop."""
def __init__(self, app):
selector = TkSelector(app)
super().__init__(selector=selector)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160226/03822b9d/attachment-0001.html>
More information about the Python-ideas
mailing list