Skip to content

Support using Tk without a mainloop #40550

Closed

Description

@noamr
mannequin
BPO 989712
Nosy @loewis, @kbkaiser, @serwy, @asvetlov
Dependencies
  • bpo-798058: IDLE / PyOS_InputHook
  • Files
  • run.py.diff
  • issue989712.diff
  • issue989712.diff: patch for 3.3 tip
  • issue989712.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/asvetlov'
    closed_at = <Date 2012-03-26.19:16:00.533>
    created_at = <Date 2004-07-12.20:16:30.000>
    labels = ['expert-IDLE', 'type-feature', 'expert-tkinter']
    title = 'Support using Tk without a mainloop'
    updated_at = <Date 2012-03-26.19:16:15.538>
    user = 'https://bugs.python.org/noamr'

    bugs.python.org fields:

    activity = <Date 2012-03-26.19:16:15.538>
    actor = 'asvetlov'
    assignee = 'asvetlov'
    closed = True
    closed_date = <Date 2012-03-26.19:16:00.533>
    closer = 'asvetlov'
    components = ['IDLE', 'Tkinter']
    creation = <Date 2004-07-12.20:16:30.000>
    creator = 'noamr'
    dependencies = ['798058']
    files = ['6090', '13440', '24830', '25031']
    hgrepos = []
    issue_num = 989712
    keywords = ['patch']
    message_count = 23.0
    messages = ['46362', '46363', '46364', '46365', '46366', '46367', '46368', '46369', '46370', '46371', '46372', '46373', '46374', '46375', '84306', '114366', '155684', '155699', '155707', '155719', '156847', '156856', '156857']
    nosy_count = 11.0
    nosy_names = ['loewis', 'kbk', 'mdehoon', 'noamr', 'dickmadden', 'ceball', 'gpolo', 'roger.serwy', 'asvetlov', 'BreamoreBoy', 'python-dev']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue989712'
    versions = ['Python 3.3']

    Activity

    1. noamr commented on Jul 12, 2004

      noamrmannequin
      MannequinAuthor

      In the regular python shell, you can open Tk windows,
      and they will operate even though you didn't call
      Tkinter.mainloop(). This is useful, for example, when
      you manipulate matplotlib graphs from within the python
      shell.
      This is done by a hook, installed when a tkapp object
      is being initialized, which handles Tk events while the
      shell is waiting for user input.

      I imitated this behaviour in IDLE: When the subprocess
      is idle, it checks whether Tkinter._default_root is set
      (this happens when the Tkinter.Tk class, which makes a
      tkapp object, is initialized, unless
      Tkinter._use_default_root is False), and if so, handles
      Tk events.

      For me it works very well.

      Have a good day,
      Noam Raphael

    2. kbkaiser commented on Jul 14, 2004

      @kbkaiser
      Contributor

      Logged In: YES
      user_id=149084

      Can you give me some more information on the hook in the
      Python interpreter? Where is it in the code?

    3. noamr commented on Jan 30, 2005

      noamrmannequin
      MannequinAuthor

      Logged In: YES
      user_id=679426

      in _tkinter.c, look for EventHook - you'll find the
      EventHook function, which is called when the interpreter is
      idle, and the Enable/Disable EventHook functions.

      In readline.c, line 765, you'll find the call to
      PyOS_InputHook, when waiting for input.

      Perhaps a more general approach would be to let Python code
      call PyOS_InputHook, for example, by defining
      readline.call_input_hook() and readline.has_input_hook().
      Then IDLE would be able to call them when idle, with no
      Tkinter-specific code.

    4. kbkaiser commented on Feb 4, 2005

      @kbkaiser
      Contributor

      Logged In: YES
      user_id=149084

      Hm, this seems closely related to Bug 798058

      I'd lost track of it because it got switched to tkinter.

    5. mdehoon commented on Feb 4, 2005

      mdehoonmannequin
      Mannequin

      Logged In: YES
      user_id=488897

      I agree, this is basically the same bug as bpo-798058. The call
      to readline.call_input_hook sounds like a good solution. But
      the hook function should be different than the current
      EventHook in _tkinter.c. That hook function sits in a loop
      until a keyboard event is noticed. A problem occurs if there
      is more than one hook function. Currently, that is not
      possible in Python, since there is only one PyOS_InputHook.
      I am working on a patch in which PyOS_InputHook is replaced
      by PyOS_AddInputHook and PyOS_RemoveInputHook, so that there
      can be more than one hook functions.

      Now suppose that there is one hook function to handle Tk
      events, and another one e.g. handling messages to windows in
      Microsoft Windows. (This is a real issue for one of my
      extension modules). If python sits in a loop in _tkinter.c's
      EventHook until a key is pressed, the MS windows won't get
      their messages.

      The following structure might work better:

      while(there is no keyboard input or other interesting event) {
                  Call PyOS_InputHook #1
                  Call PyOS_InputHook #2
                  etc.
      }
      where each of the PyOS_InputHook functions should return if
      there is no more work for them. The tricky part is to find
      out which events to wait for; some of the events may be
      handled by one of the PyOS_InputHook functions.

      Obviously I need to do some more thinking about this.

    6. mdehoon commented on Feb 8, 2005

      mdehoonmannequin
      Mannequin

      Logged In: YES
      user_id=488897

      I have written a patch that solves this problem more
      generally via PyOS_InputHook, as suggested by Noam. This
      patch also solves the related bugs bpo-1053687, bpo-798058, and
      supersedes patch bpo-1049855. The patch is available at
      http://bonsai.ims.u-tokyo.ac.jp/~mdehoon/inputhooks.diff

      Currently, the EventHook function sits in a loop handling
      Tcl events until keyboard input is detected. The presence of
      Tcl events is checked every Tkinter_busywaitinterval
      milliseconds. If a Tcl event arrives during this interval,
      it won't be handled until the end of the interval. However,
      with the default value of Tkinter_busywaitinterval = 20
      milliseconds, that delay is not noticable.

      Now consider the situation in which there can be more than
      one input hook, for example set by different extension
      modules. We cannot have EventHook sit in a loop until
      keyboard input is detected, because that would prevent other
      PyOS_InputHooks from being serviced. So in the EventHook in
      the patch, the function returns immediately after handling
      all Tcl events.

      If we use Python from the command line and open a Tkinter label:
      >>> from Tkinter import *
      >>> l = Label()
      then readline will call PyOS_InputHook ten times per second
      while Python is idle. Because PyOS_InputHook points to
      EventHook, we will return to the EventHook function almost
      immediately. Effectively, we are then in the same situation
      as before the patch. On Cygwin, however, previously mainloop
      needed to be run in order for the label to appear; this is
      no longer necessary with this patch. On Windows, currently
      PyOS_InputHook is partially broken, as it is called only
      once per command instead of ten times per second. This patch
      fixed that also (same as patch python/issues-test-cpython#1049855).

      If we have two or more input hooks, they are called
      successively by readline. Since each input hook returns
      after it has no more work to do, all of the input hooks are
      guaranteed to be serviced.

      To be able to have more than one input hook, we need to
      replace PyOS_InputHook by three functions:
      PyOS_AddInputHook, PyOS_RemoveInputHook, and
      PyOS_CallInputHooks. For the third function, the
      corresponding Python function call_input_hooks was created
      in the readline module.

      By adding a call to readline.call_input_hooks in run.py, as
      suggested by Noam, all input hook functions are serviced
      when IDLE is idle. So we can use Tkinter without calling
      mainloop, and we can use other extension packages that use
      input hooks. We can even do both:
      >>> import Tkinter
      >>> import gist # my extension module also needs input hooks
      >>> Tkinter.Label() # label appears
      >>> gist.window() # Graphics window appears.
      works both with command-line python and IDLE.

      I'm interested to hear your comments and suggestions. If
      this patch seems like the way to go, I'd be happy to write
      the documentation for it.

    7. mdehoon commented on Feb 12, 2005

      mdehoonmannequin
      Mannequin

      Logged In: YES
      user_id=488897

      Richard Madden was kind enough to test the patch at
      http://bonsai.ims.u-tokyo.ac.jp/~mdehoon/inputhooks.diff.
      This led to the discovery of two bugs in my patch and one
      preexisting bug in Tkinter.py. For this second bug, I
      submitted a separate patch (bpo-1121234). I uploaded a fixed
      patch at
      http://bonsai.ims.u-tokyo.ac.jp/~mdehoon/inputhooks.diff;
      together with patch bpo-1121234 the input hooks appear to be
      working correctly.

    8. dickmadden commented on Feb 14, 2005

      dickmaddenmannequin
      Mannequin

      Logged In: YES
      user_id=1219007

      I've tried the updated patches with Tkinter and my rasmol
      extension using the new inputhooks scheme and everything
      seems to be coexisting just fine.

    9. mdehoon commented on Mar 3, 2005

      mdehoonmannequin
      Mannequin

      Logged In: YES
      user_id=488897

      Patch bpo-1121234 (see my previous comment) was accepted and is
      now included in CVS, clearing the way for this patch.

    10. kbkaiser commented on Nov 23, 2005

      @kbkaiser
      Contributor

      Logged In: YES
      user_id=149084

      Noam, Michiel, what is the current position
      on this patch? There have been a lot of related
      patches and much discussion on python-dev.

    11. noamr commented on Nov 23, 2005

      noamrmannequin
      MannequinAuthor

      Logged In: YES
      user_id=679426

      It seems to me that the python-dev discussion didn't reach a
      conclusion. My patch is a sort of a workaround that lets you
      use Tk interactively from IDLE - it doesn't really invoke
      PyOS_InputHook. Since Tk always sets itself as
      PyOS_InputHook, it solves the Tk problem, which I think is
      the most common one.

      A more "correct" approach, which can be easily implemented,
      is to give a Python API that will call PyOS_InputHook. This
      would enable IDLE to imitate the exact behaviour of the
      textual interactive interpreter. It would have to be written
      in C, of course, and the question is where to put that C
      function: should it be in a C module which comes with IDLE,
      like the old "interrupt" module, or should a function be
      added to the "sys" or "os" modules?

    12. 12 remaining items

    13. asvetlov commented on Mar 14, 2012

      @asvetlov
      Contributor

      The issue is fixed. Thanks to Guilherme Polo.

    14. serwy commented on Mar 26, 2012

      serwymannequin
      Mannequin

      There's a subtle bug in the currently applied patch.

          import tkinter
          a = tkinter.Tk()
          b = tkinter.Tk()

      Closing the first window will prevent closing the second window. This example may seem abstract, but it is a real issue especially when using matplotlib with multiple figures.

      Attached is a patch that incorporates what IdleX uses for driving the Tk/Tcl event loop.

    15. reopened this on Mar 26, 2012
    16. reopened this on Mar 26, 2012
    17. python-dev commented on Mar 26, 2012

      python-devmannequin
      Mannequin

      New changeset 837ac3abf0c5 by Andrew Svetlov in branch 'default':
      Issue bpo-989712: update the code to process tkinter messages in IDLE
      http://hg.python.org/cpython/rev/837ac3abf0c5

    18. asvetlov commented on Mar 26, 2012

      @asvetlov
      Contributor

      Roger, your patch is pushed.

      Please next time when you reopen closed bug set 'Resolution' field to 'remind'.

      Thank you.

    19. transferred this issue fromon Apr 9, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions