Python method for reading keypress?


Question

I'm new to Python, and I just made a game and a menu in Python. Question is, that using (raw_)input() requires me to press enter after every keypress, I'd like to make it so that pressing down-arrow will instantly select the next menu item, or move down in the game. At the moment, it requires me to like type "down" and then hit enter. I also did quite a lot of research, but I would prefer not to download huge modules (e.g. pygame) just to achieve a single keyDown() method. So are there any easier ways, which I just couldn't find?

Edit: Just found out that msvcrt.getch() would do the trick. It's not keyDown(), but it works. However, I'm not sure how to use it either, it seems quite weird, any help here? This is what I got at the moment:

from msvcrt import getch
while True:
    key = getch()
    print(key)

However, it keeps giving me all these nonsense bytes, for example, down-arrow is this:

b'\xe0'
b'P'

And I have no idea how to use them, I've tried to compare with chr() and even use ord() but can't really do any comparisons. What I'm trying to do is basically this:

from msvcrt import getch
while True:
    key = getch()
    if key == escape:
        break
    elif key == downarrow:
        movedown()
    elif key == 'a':
        ...

And so on... Any help?

1
43
11/19/2017 12:02:22 AM

Accepted Answer

Figured it out by testing all the stuff by myself. Couldn't find any topics about it tho, so I'll just leave the solution here. This might not be the only or even the best solution, but it works for my purposes (within getch's limits) and is better than nothing.

Note: proper keyDown() which would recognize all the keys and actual key presses, is still valued.

Solution: using ord()-function to first turn the getch() into an integer (I guess they're virtual key codes, but not too sure) works fine, and then comparing the result to the actual number representing the wanted key. Also, if I needed to, I could add an extra chr() around the number returned so that it would convert it to a character. However, I'm using mostly down arrow, esc, etc. so converting those to a character would be stupid. Here's the final code:

from msvcrt import getch
while True:
    key = ord(getch())
    if key == 27: #ESC
        break
    elif key == 13: #Enter
        select()
    elif key == 224: #Special keys (arrows, f keys, ins, del, etc.)
        key = ord(getch())
        if key == 80: #Down arrow
            moveDown()
        elif key == 72: #Up arrow
            moveUp()

Also if someone else needs to, you can easily find out the keycodes from google, or by using python and just pressing the key:

from msvcrt import getch
while True:
    print(ord(getch()))
58
11/19/2017 10:29:59 PM

See the MSDN getch docs. Specifically:

The _getch and_getwch functions read a single character from the console without echoing the character. None of these functions can be used to read CTRL+C. When reading a function key or an arrow key, each function must be called twice; the first call returns 0 or 0xE0, and the second call returns the actual key code.

The Python function returns a character. you can use ord() to get an integer value you can test, for example keycode = ord(msvcrt.getch()).

So if you read an 0x00 or 0xE0, read it a second time to get the key code for an arrow or function key. From experimentation, 0x00 precedes F1-F10 (0x3B-0x44) and 0xE0 precedes arrow keys and Ins/Del/Home/End/PageUp/PageDown.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon