1

I've remade this simpler version of Python 3.8 code that emulated some undesired behaviour in my program running on Windows 10. The main external dependency is this keyboard module:

import keyboard
from time import sleep


def get_key() -> str:
    """
    Get the user-pressed key as a lowercase string. E.g. pressing the spacebar returns 'space'.
    :return: str - Returns a string representation of the pressed key.
    """

    print(f"Press any key...")

    while True:
        pressed_key: str = str(keyboard.read_key()).lower()

        if not keyboard.is_pressed(pressed_key):  # Wait for key release or keyboard detects many key presses.
            break
        else:
            continue

    return pressed_key


def main() -> None:
    pressed_key: str = get_key()

    print(f"You have pressed: '{pressed_key}'.")
    sleep(1)
    input("Now take other user input: ")


if __name__ == "__main__":
    main()

when running python ./my_script.py in the terminal and pressing a random key (say 'g'), I get the following output:

> Press any key...
> You have pressed: 'g'.
> Now take other user input: g

The issue is that when the program gets to the builtin input() function, the character 'g' is prepopulated in the terminal. This is problematic if, say, the initial user input is 'enter' and the input function is then skipped without ever getting input from the user. Also, it can populate user input data unwanted characters.

Is there a simple way to:

  1. Temporarily move focus away from the terminal?
  2. Flush the stdin? (sys.stdin.flush() sadly does not work)
  3. Use 'keyboard' in a different way such that this double character recording behaviour does not occur?

All questions and responses are welcome, thank you.

GBean
  • 41
  • 9
  • 1
    Try https://stackoverflow.com/questions/2520893/how-to-flush-the-input-stream-in-python (I tried your code on windows and experienced the issue, and flushing with msvcrt fixed it). – Adam Feor Sep 03 '21 at 13:08
  • That sounds promising, I'll give that a go! For the long-term, I would prefer an OS agnostic solution if possible. Thank you though! – GBean Sep 03 '21 at 13:10
  • Sadly, in the docs for `msvcrt` for `getch()`, the docs say "will not wait for 'Enter' to be pressed." This is annoying as I'd like to use the 'Enter' key for an action in my main code. – GBean Sep 03 '21 at 13:21

1 Answers1

0

I have been able to temporarily resolve the issue by using the suppress=True keyword argument for the read_key() function.

NOTE: This 'solution' still has key functions that persist after the execution of the program so characters will appear in your terminal input line.

Solution:

def get_key() -> str:
    """
    Get the user-pressed key as a lowercase string. E.g. pressing the spacebar returns 'space'.
    :return: str - Returns a string representation of the pressed key.
    """

    print(f"Press any key...")

    while True:
        pressed_key: str = str(keyboard.read_key(suppress=True)).lower()

        if not keyboard.is_pressed(pressed_key):  # Wait for key release or keyboard detects many key presses.
            break
        else:
            continue

    return pressed_key
GBean
  • 41
  • 9