Python 3: Strange behavior of msvcrt.getch(), the command used to read individual keypresses

836 views Asked by At

Simple version of the problem:

Here I want to print three numbers in sequence, but the user has to press a key between 2 and 3:

import msvcrt

print("1");
print("2");
msvcrt.getch();
print("3");

Obviously, it prints:

1
2

Then waits for the keypress, to then print 3 on a new line below 2. But, what if I decide that I don't want a line break between 2 and 3? Considering I want 2 and 3 to be printed right next to eachother, I would change the code to:

import msvcrt

print("1");
print("2", end="");
msvcrt.getch();
print("3");

But, instead of printing 1 and 2, it just prints

1

and only after I press the key it prints the remaining two numbers

1
23

What's the problem of msvcrt.getch() with not wanting to wait on a written line?

Normal version of the problem (closer to what my program looks like):

I'm making a program that captures each character entered by the user and prints them as the user writes a question (this is important because it will feature a trick that needs to know exactly what the user wrote before pressing ENTER):

import msvcrt
import sys
import os

def main():

    question = "";
    ch = "a";

    while ch != '\r':

        absolutely_unused_variable = os.system('cls');
        print("Make a question:");
        print(question, end="");
        ch = msvcrt.getch().decode('utf-8');
        question = question + ch;

    print("end");

if __name__ == '__main__':
    main();

Right now, I would expect the output to look like the code was just

import os

os.system('cls');
print("Make a question:");
question = input();

Instead, it prints what I type before the prompt text, and not even printing each character as I type them. This is the output after I type "EXAMPLE":

EXAMPLMake a question:

And after I press ENTER:

EXAMPLMake a question:
EXAMPLEend

I continued messing around with the code trying to find some sort of logic, but the bottom line is that simply, msvcrt.getch() only correctly registers individual keypresses if they're on a newly created line. What can I do to make the program exactly how I want then?

1

There are 1 answers

1
Laurent LAPORTE On BEST ANSWER

In the code below:

print("1");
print("2", end="");
msvcrt.getch();
print("3");

The "2" appears after the key is pressed, because the stdout stream is flushed after the "3" is printed.

You can try this:

import sys

print("1");
print("2", end="");
sys.stdout.flush()
msvcrt.getch();
print("3");

See also “How to flush output of Python print?” on SO.