I am using msvcrt.getch()
to read input in a Python script. It works fine, most of the time, but when pressing Shift
plus an arrow key, I only receive the code for that arrow key.
Is there a way of reading these key combinations using getch()
alone? I'd prefer doing this way rather than with other methods since I'm hoping to write this to work on Linux as well, and from what I can tell anything other than regular input requires root on there.
The reason that I think this may be possible is because PowerShell reads Shift + <arrow keys>
to handle text selection. Is this because PowerShell is reading input in a different way? Does it have different permissions?
The Shift
key is considered as a special key. According to the documentation
Read a keypress and return the resulting character as a byte string. Nothing is echoed to the console. This call will block if a keypress is not already available, but will not wait for Enter to be pressed. If the pressed key was a special function key, this will return '\000' or '\xe0'; the next call will return the keycode. The Control-C keypress cannot be read with this function.
As getch is limited, we can use the ctypes
library which provides more information, such as the keystates
. We use the & 0x8000
to mask the high bit and if it's not a zero, the shift is held down.
Here is what it would look like
import msvcrt
import ctypes
key = msvcrt.getch()
if key == b'\xe0': # Escape sequence for special keys
print("Special key")
key = msvcrt.getch()
if key == b'H':
print("Up arrow")
elif key == b'P':
print("Down arrow")
elif key == b'M':
print("Right arrow")
elif key == b'K':
print("Left arrow")
# Check for Shift using `GetKeyState` from ctypes
if (ctypes.windll.user32.GetKeyState(0x10) & 0x8000) != 0:
print(" with Shift")