Python Method for Reading Keypress

Python method for reading keypress?

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()))

Is there a way to read keypresses from the Enter key?

How to bind and handle events

Use bind(sequence, func) method on your widget (like Button or even the root app Tk).

The parameter sequence is one of the predefined events, a string name for keys, mouse-events, etc.
The parameter func is a callback or handler function, given by name only (without parentheses or arguments), which must have one positional parameter for Event.

Demo

See this minimal example:

from tkinter import *

def callback(event):
print(event)

def quit(): # did we miss something ?
print("Escape was pressed. Quitting.. Bye!")
exit()

app = Tk()
app.bind('<Return>', callback) # on keypress of Enter or Return key
app.bind('<Enter>', callback) # on mouse-pointer entering the widget - here the app's root window (not confuse with Enter key of keyboard)
app.bind('<Escape>', quit) # on keypress of Escape key

app.mainloop() # to start the main loop listening for events

Prints after following keys pressed:

  1. Enter key was pressed
  2. Escape key was pressed
<KeyPress event keysym=Return keycode=36 char='\r' x=-583 y=-309>
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
TypeError: quit() takes 0 positional arguments but 1 was given

Note:

  1. The Enter key was caught and bound callback/handler function (callback) invoked which prints the passed event.
  2. The Escape key was caught and bound callback/handler function (quit) invoked. But since it hasn't the required parameter (like event) the invocation failed with a TypeError.

When adding the parameter def quit(event): it succeeds:

<Enter event focus=True x=6 y=188>
<Enter event focus=True x=182 y=45>
<KeyPress event keysym=Return keycode=36 char='\r' x=-583 y=-309>
<Enter event state=Button1 focus=True x=123 y=68>
Escape was pressed. Quitting.. Bye!

Note:

  1. The <Enter> event is when the mouse-pointer enters the (visible) widget frame, here of the application's root window.
  2. The <Escape> event exits the application

Further reading

RealPython: Python GUI Programming With Tkinter is a rich tutorial to learn more, especially on Using .bind().

Simplest method to call a function from keypress in python(3)

You can intercept the ctrl+c signal and call your own function at that time rather than
exiting.

import signal
import sys

def exit_func(signal, frame):
'''Exit function to be called when the user presses ctrl+c.
Replace this with whatever you want to do to break out of the loop.
'''
print("Exiting")
sys.exit(0) # remove this if you do not want to exit here

# register your exit function to handle the ctrl+c signal
signal.signal(signal.SIGINT, exit_func)

#loop forever
while True:
...

You should replace sys.exit(0) with something more useful to you. You could raise an exception and that except on it outside the loop body (or just finally) to perform your cleanup actions.

Key Presses in Python

Install the pywin32 extensions. Then you can do the following:

import win32com.client as comclt
wsh= comclt.Dispatch("WScript.Shell")
wsh.AppActivate("Notepad") # select another application
wsh.SendKeys("a") # send the keys you want

Search for documentation of the WScript.Shell object (I believe installed by default in all Windows XP installations). You can start here, perhaps.

EDIT: Sending F11

import win32com.client as comctl
wsh = comctl.Dispatch("WScript.Shell")

# Google Chrome window title
wsh.AppActivate("icanhazip.com")
wsh.SendKeys("{F11}")

Python Module for detecting Keyboard Strokes

You can use the keyboard library
And than to detect if one of the keys was pressed, use

import keyboard
for key in "wasd":
keyboard.add_hotkey(key, print, args=[key])

keyboard.wait()

This will print w, a, s or d if you press one of them.
The keyboard.wait() is there for the code to not stop running

How can I read keyboard input in Python

So for instance you have a Python code like this:

file1.py

#!/bin/python
... do some stuff...

And at a certain point of the document you want to always check for input:

while True:
input = raw_input(">>>")
... do something with the input...

That will always wait for input. You can thread that infinite loop as a separate process and do other things in the meanwhile, so that the user input can have an effect in the tasks you are doing.

If you instead want to ask for input ONLY when a key is pressed, and do that as a loop, with this code (taken from this ActiveState recipe by Steven D'Aprano) you can wait for the key press to happen, and then ask for an input, execute a task and return back to the previous state.

import sys

try:
import tty, termios
except ImportError:
# Probably Windows.
try:
import msvcrt
except ImportError:
# FIXME what to do on other platforms?
# Just give up here.
raise ImportError('getch not available')
else:
getch = msvcrt.getch
else:
def getch():
"""getch() -> key character

Read a single keypress from stdin and return the resulting character.
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 modifier key, nothing will be detected; if
it were a special function key, it may return the first character of
of an escape sequence, leaving additional characters in the buffer.
"""
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch

So how to deal with this? Well, now just call getch() every time you want to wait for a key press. Just like this:

while True:
getch() # this also returns the key pressed, if you want to store it
input = raw_input("Enter input")
do_whatever_with_it

You can also thread that and do other tasks in the meanwhile.

Remember that Python 3.x does no longer use raw_input, but instead simply input().



Related Topics



Leave a reply



Submit