[New-bugs-announce] [issue41176] revise Tkinter mainloop dispatching flag behavior
report at bugs.python.org
Tue Jun 30 16:44:35 EDT 2020
New submission from Richard Sheridan <richard.sheridan at gmail.com>:
This could also be considered a "behavior" type issue.
`TkappObject` has a member `dispatching` that could usefully be exposed by a very simple read-only method for users to determine at runtime if the tkinter mainloop is running. Matplotlib and I'm sure other packages rely on fragile hacks (https://github.com/matplotlib/matplotlib/blob/a68562aa230e5895136120f5073dd01f124d728d/lib/matplotlib/cbook/__init__.py#L65-L71) to determine this state. I ran into this in https://github.com/matplotlib/matplotlib/pull/17802. All these projects would be more reliable with a new "dispatching()" method on the TkappObject, tkinter.Misc objects, and possibly the tkinter module itself.
Internally, `dispatching` is used to, yes, determine if the mainloop is running. However, this determination is always done within the `WaitForMainloop` function (https://github.com/python/cpython/blob/bd4a3f21454a6012f4353e2255837561fc9f0e6a/Modules/_tkinter.c#L363-L380), which waits up to 1 second for the mainloop to come up. Apparently, this function allows a thread to implicitly wait for the loop to come up by calling any `TkappObject` method. This is a bad design choice in my opinion, because if client code wants to start immediately and the loop is not started by mistake, there will be a meaningless, hard-to-diagnose delay of one second before crashing. Instead, if some client code in a thread needs to wait for the mainloop to run, it should explicitly poll `dispatching()` on its own. This waiting behavior should be deprecated and, after a deprecation cycle perhaps, all `WaitForMainloop()` statements should be converted to inline `self->dispatching`.
The correctness of the `dispatching` flag is dampened by the currently existing, undocumented `willdispatch` method which simply arbitrarily sets the `dispatching` to 1. It seems `willdispatch` was added 18 years ago to circumvent a bug building pydoc caused by `WaitForMainloop` not waiting long enough, as it tricks `WaitForMainloop` into... not waiting for the mainloop. This was in my opinion a bad choice in comparison to adding a dispatching flag: again, if some thread needs to wait for the mainloop, it should poll `dispatching()`, and avoid adding spurious 1 second waits. `willdispatch` currently has no references in CPython and most GitHub references are to Pycharm stubs for the CPython method. It should be deprecated and removed to preserve the correctness of `dispatching`.
Happy to make a PR about this, except I don't understand clinic at all, nor the specifics of deprecation cycles in CPython.
nosy: Richard Sheridan
title: revise Tkinter mainloop dispatching flag behavior
versions: Python 3.10, Python 3.5, Python 3.6, Python 3.7, Python 3.8, Python 3.9
Python tracker <report at bugs.python.org>
More information about the New-bugs-announce