I'm trying to invoke functions on key press in python. When the script is run in Windows command line (cmd.exe), everything works as expected. But usually when I'm on Windows, I use mintty.
In mintty, the application behaves different. The getch()
blocks the application (forever).
import msvcrt
print("press a key")
char = msvcrt.getch()
print(f"you pressed: {char}")
In Windows command line:
press a key
(I press the a key)
you pressed: b'a'
(application closed as it should)
In mintty:
press a key
(i press a multiple times)
aaaaaaaaaaaaaa
(nothing happens)
The short answer is "ensure the windows python executable call is wrapped in a winpty
call".
I have a similar challenge, where I expect to support a fully interactive console application which uses termios
in unixey environments and msvcrt
in Windows.
mintty
, so supporting termios
), butThe biggest remaining challenge I see here is detecting that failure.
So far, I have conditions along the following:
msvcrt
was loaded (we're running in windows python)os.environ.get('TERM_PROGRAM') == "mintty"
(mintty was the console)os.environ.get('TERM') == "xterm"
(winpty hasn't changed the terminal type from mintty's xterm default)winpty
This relies on a strange series of coincidences on my system:
None
(in python terms)Unfortunately, I don't believe this logic is very reliable - other versions of winpty and mintty may behave differently, and users may have changed the terminal type setting in mintty to something other than "xterm", in which case my script will incorrectrly assume everything is OK.
I would dearly love a more reliable way to detect when my script is in "python for windows running in mintty without winpty".
For what it's worth, if you can rely on having bash available in the path (which, if you're trying to detect mintty from python, is actually quite likely I guess?), then you can:
-i
, so it connects to the terminal, and with)echo -n -e
to print the escape sequenceread
with a timeout to capture the tty responseExample bash script:
echo -n -e '\e[>c';
read -rs -t 0.2 -d "" <$(tty)
echo "Look ma! Secondary device attributes are ${REPLY#?} - now if they start with [>77; then I know I'm in mintty."