This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author terry.reedy
Recipients Maxime S, gvanrossum, serhiy.storchaka, terry.reedy, yselivanov
Date 2016-07-20.04:38:36
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1468989521.03.0.854074314481.issue27546@psf.upfronthosting.co.za>
In-reply-to
Content
Guido, that seems like a reasonable roadmap.  The examples directory is not in the CPython repo, but I found it here.
https://github.com/python/asyncio/tree/master/examples

For a demo based on crawl.py, the goal would be a live status report.  Perhaps as files are fetched, they could be entered into a Treeview-based url tree, with columns for the statistics. (I still have to learn to practical use of Treeview.)  This would require adding widget data insertion commands within the crawl code.  Who actually wrote it, that would understand it?

Responsiveness should be a matter of prioritizing events.  Using the  asyncio loop as a base, I did the minimum needed for the first demo and for the initial part of the follow-up below.  For general use, _run_once should be modified to always let gui events be handled 'soon' by either not blocking or having a short timeout.  The root.update call could be moved from run_forever to multiple places within _run_once.  At an extreme, the _process_events implementations could be modified to call root.update() after processing each io event.  According to timeit.timeit(root.update), a do-nothing call takes less than 4 microseconds on my machine.

---

I implemented my idea of updating a tk widget in an async for loop.  The attached tkaloop does so, with the syntax I proposed previously.  There is only a change to the timer api.  With respect to the datetime clock, the behavior is essentially the same as with the first code.

Given that one can do the same thing with a normal for loop and explicit update (as some beginners try to do), is this useful?

1. Responsiveness: A normal for-loop blocks, freezing the gui.  To test that this is not so here, I added a button to do something visible - change a background color.  While the clock is running, it only sort-of works, because clicks are only processed after each 1 second tick.  The reason is that the select call in _run_once gets a timeout that is the minimum time to a scheduled event.  (The same should be true in tkloop.py if similarly modified.)  The next step is to modify _run_once as discussed above.

Tk allows one to specify delays to the nearest millisecond and on my machine, that precision is real.

from tkinter import *
import time
        
root = Tk()
root.withdraw()
timer = time.perf_counter
##n = 999
##delay = 1
n=1
delay=337
def tick():
    global n
    if n:
        n -= 1
        root.after(delay, tick)
    else:
        print(timer() - start)

tick()
start = timer()
root.mainloop()

prints .3370... in multiple runs. 1000 loops with a delay of 1 ms takes 1.05... seconds.  Similar performance would be a target for run_forever.

2. Parallel looping.  Supposed we wanted to automate the background color changes, with an interval of, say x seconds.  If x is, say, .3, then one could use .1 second ticks and an update block that flips the background every 3 ticks and the clock every 10.

But what if the intervals are not so conveniently commensurable or the separate updates not so easily mashed together into one loop block?
Parallel looping with chained callbacks, whether with tk or asyncio is fairly easy.  I presume it could be done with asyncio coroutines (but have no experience).  What I would like, but cannot see, is a way to do so with async for.  Within a function, async for blocks execution of remaining code after the for statement the same as normal for statement.

My conclusion thus far: with the response issue solved, a single async for loop could work for some time-driven applications, including some that beginners write, but not all.

An alternative for reducing the callback boilerplate is an animate function.  I have thought of writing one for tkinter, but have not yet because I have not yet needed one for IDLE.
History
Date User Action Args
2016-07-20 04:38:41terry.reedysetrecipients: + terry.reedy, gvanrossum, serhiy.storchaka, yselivanov, Maxime S
2016-07-20 04:38:41terry.reedysetmessageid: <1468989521.03.0.854074314481.issue27546@psf.upfronthosting.co.za>
2016-07-20 04:38:41terry.reedylinkissue27546 messages
2016-07-20 04:38:38terry.reedycreate