pythongetchmintty

How can I make msvcrt.getch() behave the same way in mintty as in cmd?


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)


Solution

  • 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.

    The biggest remaining challenge I see here is detecting that failure.

    So far, I have conditions along the following:

    This relies on a strange series of coincidences on my system:

    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".

    UPDATE: Using Bash can work!

    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:

    Example 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."