-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
Description
Bug report
Bug description:
When using tkinter in an interactive Python session, the EventHook
function in Modules/_tkinter.c
runs the Tcl/Tk event loop, and exits once data become available on stdin (i.e., when the user types in the next Python command).
The EventHook
function uses the Tcl_CreateFileHandler
function to monitor for activity on stdin.
As was already noticed in the original commit (of 23 May 1998; 7bf1564), this does not work on Windows, as Tcl_CreateFileHandler
Unix-only (https://www.tcl-lang.org/man/tcl8.6/TclLib/CrtFileHdlr.htm).
Instead, for Windows the _kbhit
function of Microsoft Windows (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/kbhit?view=msvc-170) is used to check if a key has been pressed (commit of 13 June 1998; ad4db17).
As _kbhit
checks for a physical key stroke on a console, it does not work if stdin is redirected to a pipe.
The script below shows an example. On Unix and Mac, running this script as python script.py
causes 'hello' to be printed immediately. On Windows, the script starts running but does not print anything to screen and does not exit until the user presses some key on the keyboard.
Though most users won't need to use a pipe for stdin, being able to pipe to stdin is important as it will let you test tkinter interactive usage from a script (for example as part of the cpython test suite).
It's fairly straightforward to fix this bug by replacing Tcl_CreateFileHandler
by Tcl_CreateChannelHandler
, and using Tcl_GetStdChannel(TCL_STDIN)
to get a channel for stdin.
import sys
import subprocess
proc = subprocess.Popen([sys.executable, "-i"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
_ = proc.stdin.write(b"import tkinter\n")
_ = proc.stdin.write(b"interpreter = tkinter.Tcl()\n")
_ = proc.stdin.write(b"print('hello')\n")
_ = proc.stdin.write(b"quit()\n")
stdout, stderr = proc.communicate()
stdout = stdout.decode()
stderr = stderr.decode()
print(stdout)
CPython versions tested on:
CPython main branch
Operating systems tested on:
Windows, macOS, Linux