Unbuffered character input for python on a windows

2019-02-19 10:45发布

问题:

What I am trying to do

I am trying to design a stopwatch with lap timing. When you press "L" then a lap is completed and when you press "S" all laps are completed and the timings are displayed in order.

While in C++ I can do this with the function _getch() from conio.h and it would be quite easy. I want to write this program in python as it would be a lot more easier and also the time handling in C++ proved to be hard.

Still I did write a program (which was for cube timing) on this link: Cube timer

Problem

There is no function like _getch(). And this is a problem because at the end of a lap you can't press a key and an enter key because it would be time taking and irritating for the user.

things I read

I read about the curses library but alas it has no windows port.

I tried a program that was supposed to work according to the website. This was from the link

Link to getch recipe

But it did not work.

What I tried:

  1. msvcrt.getch()

    >>> import msvcrt
    >>> msvcrt.getch()
    '\xff'

I believe that FF is the hexadecimal equivalent of 255.

I did not understand why this is happenning.

  1. readch() as sugggested in @martineau

    import msvcrt

    def readch(echo=True): "Get a single character on Windows." while msvcrt.kbhit(): # clear out keyboard buffer msvcrt.getch() ch = msvcrt.getch() while ch in '\x00\xe0': # arrow or function key prefix? msvcrt.getch() ch = msvcrt.getch() # second call returns the actual key code if echo: msvcrt.putch(ch) return ch.decode()

    a = []

    for i in range(10): a.append(readch())

The error that i got:

>>> 

Traceback (most recent call last):
  File "C:/Python25/1.py", line 30, in <module>
    a.append(readch())
  File "C:/Python25/1.py", line 25, in readch
    return ch.decode()
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)

What I need help with

A function that works like _getch() or something equivalent that works on a windows machine.

Machine specs

Python IDLE 2.5.4 or 2.6 or 2.7

Windows XP SP3

回答1:

This is what I've used that seems to work in a Windows console. It's somewhat similar to that ActiveState recipe except that it only works on Windows. It's based on this msdn documentation for _getwch().

#### windows only ####
import msvcrt

def readch(echo=True):
    "Get a single character on Windows."
    while msvcrt.kbhit():  # clear out keyboard buffer
        msvcrt.getwch()
    ch = msvcrt.getwch()
    if ch in u'\x00\xe0':  # arrow or function key prefix?
        ch = msvcrt.getwch()  # second call returns the actual key code
    if echo:
        msvcrt.putwch(ch)
    return ch

def pause(prompt='Press any key to continue . . .'):
    if prompt:
        print prompt,
    readch(echo=False)

(Updated to handle Unicode).



回答2:

If you are asking about how to read input without input, you probably are looking for binding This requires a Tkinter window, I believe.

lapEnded = bind_all("<KeyPress-l>", endLap)
stopRunning = bind_all("<KeyPress-s", noMoreRunning)

Then, you define the functions endLap and noMoreRunning, which do their functions. Depending on your version of Tkinter and/or Python, bind_all may simply be bind. Hope this answers your question.