Terry J. Reedy added the comment: > wasting battery power ?! We live in slightly different computing universes > ;-). But I get the point. The last two files I uploaded use call_later and > I should stick with that. I should also add a note that the innermost > asyncio loop function sleeps when there is nothing to do and that the tk > updater wakes it up, if necessary, to check for gui events even when there > are none. Updater is polling rather than interrupt based. Or in other > words, it interrupts asyncio to poll tk.
I should also say that the update interval is passed in to the class so one can make an instance-specific tradeoff between overhead and responsiveness and display update frequency. A read-only display might be updated just once a minute. If loop.call_later(0.1, tk_update) is actually a problem on a system, then IDLE would likely be twice as bad, as it also has a busy loop in the user process, polling both the socket connection and calling tk update 20 times a second. There are also loops in the IDLE process. I agree on the ideal solution and on the key component, which is to sleep until there is a ready Task or file event. _run_once does this in the select call by adjusting the timeout to the minimum time to the next ready task (possibly 0). Tcl has such a component, with the addition of simultaneously waiting for window events -- but it only only includes file events on unix. (It took a brave and talented group to try to reconcile the Unix and Windows models.) Here is a simplified Python version of Tcl_DoOneEvent. http://www.tcl.tk/man/tcl8.6/TclLib/DoOneEvent.htm Tcl has window, file, timer, and idle events. Window events include user key and mouse events and other from the graphics system. The first three types all go in one ready queue. Idle events are those that affect what the user sees on the screen and go in a separate, lower-priority queue. def do_one_event(sleep_ok): if ready: process(ready.pop()) return True load_ready() if ready: process(ready.pop()) return True if idle: for event in idle: process(event) return True if sleep_ok: sleep_until_event() # the hard part load_ready() process(ready.pop()) return True else: return False def load_ready(): # In some unspecified order ready.extend(get_window_events) # graphics system ready.extend(get_file_events) # select ready.extend(get_timer_events) # priority queue pops Update processes all events available without sleeping. http://www.tcl.tk/man/tcl8.6/TclCmd/update.htm Mainloop continues (with sleeps) while there are toplevels and not stopped. def update(): while(do_one_event(sleep_ok=False)): pass def mainloop(): while toplevels and not stop: do_one_event() Sleep_ok is actually a dont_sleep bit flag. DoOneEvent has other flags to select which types of event to process. Hence def update_idletasks() # all currently ready do_one_event(dont_sleep | idletasks) It is possible for the idle queue to get starved for attention. Hence the existence of update_idletasks and recommendations to call it in certain situations. It would also be possible to call (from Python, via tcl) do_one_event(dont_sleep | gui_events) IF it were known that a gui event was ready to be retrieved. It is knowing that, without polling in a 'busy loop' that is hard to impossible. If it were possible, an extra call to do idletasks would also be needed.. In summary, I see this as a situation where practicality beats a possibly unattainable purity. ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue27546> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com