<div dir="ltr"><div><div>I wonder if you could look at Tkinter for a very different view of the world. While there are ways to integrate socket I/O with the Tcl/Tk event loop, the typical Python app using Tkinter probably moves network I/O (if it has any) to a separate thread, and ignores the delays of disk-based I/O (because modern disk I/O is usually faster than the minimal event response time -- assuming you don't have floppy disks :-).<br><br></div>I'm not entirely sure how you would use coroutines with Tkinter, but I could imagine that e.g. mouse tracking code such as found in drawing apps might be written more easily using a loop that uses await (or yield [from]) to get another event rather than as a callback function for the "mouse move" event.<br><br></div>The mechanics of writing a multiplexer that receives Tkinter events and uses them to decide which generator/coroutine to wake up might be too much for your purpose, but it would provide a real-life example of an event loop that's not built for network I/O.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, May 5, 2015 at 3:52 PM, Paul Moore <span dir="ltr"><<a href="mailto:p.f.moore@gmail.com" target="_blank">p.f.moore@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 5 May 2015 at 23:28, Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:<br>
>> At this point, *all* I'm thinking of is a toy. So, an implementation<br>
>> somewhat parallel to asyncio, but where the event loop just passes<br>
>> control to the next task - so no IO multiplexing. Essentially Greg<br>
>> Ewing's example up to, but not including, "Waiting for External<br>
>> Events". And ideally I'd like to think that "Waiting for Resources"<br>
>> can be omitted in favour of reusing<br>
>> <a href="https://docs.python.org/3/library/asyncio-sync.html" target="_blank">https://docs.python.org/3/library/asyncio-sync.html</a> and<br>
>> <a href="https://docs.python.org/3/library/asyncio-queue.html" target="_blank">https://docs.python.org/3/library/asyncio-queue.html</a>. My fear is,<br>
>> however, that those parts of asyncio aren't reusable for other event<br>
>> loops, and every event loop implementation has to reinvent those<br>
>> wheels.<br>
><br>
> It was never a goal of asyncio to have parts that were directly reusable by<br>
> other event loops without pulling in (almost) all of asyncio. The<br>
> interoperability offered by asyncio allows other event loops to implement<br>
> the same low-level interface as asyncio, or to build on top of asyncio.<br>
> (This is why the event loop uses callbacks and isn't coroutines/generators<br>
> all the way down.) Note that asyncio.get_event_loop() may return a loop<br>
> implemented by some other framework, and the rest of asyncio will then use<br>
> that event loop. This is enabled by the EventLoopPolicy interface.<br>
<br>
</span>OK, that's an entirely fair comment. It's difficult to tell from the<br>
docs - there's nothing obviously io-related about the task<br>
abstraction, or the synchronisation or queue primitives. But there's<br>
equally no reason to assume that they would work with another<br>
implementation. As I mentioned somewhere else, maybe refactoring the<br>
bits of asyncio that can be reused into an asynclib module would be<br>
useful. But based on what you said, there's no reason to assume that<br>
would be an easy job. And without another event loop implementation,<br>
it's not obvious that there's a justification for doing so.<br>
<span class=""><br>
> What do you hope to learn or teach by creating this toy example? And how do<br>
> you define "a complete event loop"?<br>
<br>
</span>Well, one thing I hope to learn, I guess, is what "a complete event<br>
loop" consists of :-)<br>
<br>
More broadly, I'd like to get a better feel for what methods are<br>
fundamental to an event loop. IIRC, we had this discussion way back at<br>
the beginning of the asyncio development when I was unclear about why<br>
create_connection had to be an event loop method. In the asyncio<br>
context, it has to be because the event loop needs to know when<br>
connections get created (excuse me probably misremembering the exact<br>
reason from back then). But conversely, it's easy to imagine an event<br>
loop unrelated to socket IO that doesn't have a create_connection<br>
method. On the other hand, an event loop with no call_soon method<br>
seems unlikely. So in essence I'm thinking about what a "sensible<br>
minimum" event loop might be. An event loop ABC, if you like.<br>
<br>
And following on from there, what useful abstractions (tasks,<br>
synchronisation and queue primitives) can be built on top of such a<br>
minimal interface. Basically, that's what I'm hoping to learn - what<br>
is fundamental (or at least generally applicable) and what is related<br>
to the purpose of a given implementation.<br>
<br>
I've probably got enough from this discussion to try writing up some<br>
code and see where it leads me.<br>
<br>
Paul<br>
<br>
PS You mentioned that a the callback-based nature of the asyncio event<br>
loop is to simplify interoperability with callback-based frameworks<br>
like Twisted. I guess the above ignores the possibility of event loops<br>
that *aren't* callback-based. Or maybe it doesn't - that's possibly<br>
another class of methods (callback-focused ones) that maybe can be<br>
separated into their own ABC.<br>
</blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div>