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 mdehoon
Recipients
Date 2003-08-31.08:45:24
SpamBayes Score
Marked as misclassified
Message-id
In-reply-to
Content
[This bug report is a follow-up of a discussion with
Matthew Cowler of help@python]

I noticed an inconsistency with the usage of the
PyOS_InputHook variable between Python 2.3's IDLE and
Python run from the (DOS or linux) command prompt. This
problem does not occur with earlier versions of Python.
First I will describe the problem, then why it is
important to me.

The PyOS_InputHook variable can be used to install a
callback function that gets called periodically (via
readline's rl_event_hook) when Python is waiting for
terminal input. When Python is run as a terminal
application (from the DOS or linux command prompt),
PyOS_InputHook is NULL initially. Python C extension
modules can set PyOS_InputHook to a function which is
to be called periodically. This works with Python 2.3
and older versions.

In Python 2.2, IDLE makes use of the PyOS_InputHook
variable, presumably to get messages delivered to the
Tkinter window. Python C extension modules that are
loaded from IDLE find that PyOS_InputHook is not NULL,
and therefore cannot specify a different callback
function via PyOS_InputHook, as that would freeze the
Tkinter window.

Now on Python 2.2, in practice that is not a problem.
IDLE in Python 2.2 runs in a single thread. This thread
contains a message loop (probably hidden in the Tk
library) that takes care of the messages destined for
the Tk window. If we open an additional (non-Tk) window
from our C extension module, then its messages also get
processed by Tk's message loop as it is running in the
same thread. So we don't need an additional message
loop for our non-Tk window, and we don't need to change
PyOS_InputHook.

In Python 2.3, IDLE works differently, as it talks to
its interactive interpreter on the TCP/IP loopback
interface and does not make use of PyOS_InputHook. If I
import my C extension module from IDLE, it shows that
PyOS_InputHook is NULL. In addition, multithreading is
now used, with three threads on Windows and two on
Linux and Mac OS X. (I am not sure where the additional
thread on Windows is coming from). In particular, the C
extension module and Tk's message loop are running in
separate threads. So if I open a non-Tk window from my
C extension module, its messages are not handled by
Tk's message loop.

The solution would be to have a message loop in my C
extension module also, which is how the C extension
module works when Python is run as a terminal
application. As PyOS_InputHook is NULL (both with and
without IDLE) when I import my extension module, I can
point it to a message loop in the extension module
without causing havoc. However, whereas Python without
IDLE calls the function specified by PyOS_InputHook
correctly, Python with IDLE fails to call
PyOS_InputHook. Hence, with IDLE I am stuck in a thread
without a message loop, and no way to provide a message
loop of my own.

If I run IDLE with the "-n" command-line argument to
disable running Python code in a sub-process, there is
only one thread, and I can use that thread's message
loop without problems.

Would it be possible in Python 2.3 to have
PyOS_InputHook called also if IDLE / Tkinter is
running? I would think that that no longer interferes
with the correct operation of Tkinter / IDLE, as after
importing IDLE, PyOS_InputHook is NULL anyway.


This problem is important to me because of the
Windows-port of Pygist (gist scientific plotting
package for Python), which I codeveloped several months
ago. The core graphics routines of Pygist are written
in C for performance reasons. Pygist does not work with
Python 2.3 with IDLE, while it does work with Python
2.2 with IDLE. There are no problems with Python 2.3
run from the DOS command prompt, nor with PythonWin or
PyShell.

The problem with Python 2.3 with IDLE is that the
graphics window no longer receives its messages. In
usual Windows programs, there is one message loop,
which looks like

while (GetMessage(&msg, NULL, 0, 0))
{ TranslateMessage(&msg);
  DispatchMessage(&msg);
}

In Python 2.2 with IDLE, we use Tk's message loop to
get messages delivered to the Pygist graphics window.
When running Python 2.2 and Python 2.3 as a terminal
application, we start our own message loop in the C
extension module and point to it using PyOS_InputHook.
With Python 2.3 with IDLE, Tk's message loop is in a
separate thread, so we can't use it, while at the same
time PyOS_InputHook is being ignored. Hence Pygist's
graphics window freezes.

Note that Pygist is different from many other plotting
packages for Python, as it returns to the Python prompt
after opening a graphics Window (allowing you to modify
the window interactively). So the trick is to let both
the Python interpreter and the graphics window receive
their messages.


With regards,

Michiel de Hoon, University of Tokyo.
History
Date User Action Args
2007-08-23 14:16:34adminlinkissue798058 messages
2007-08-23 14:16:34admincreate