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:
- Enter key was pressed
- 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:
- The Enter key was caught and bound callback/handler function (
callback
) invoked which prints the passedevent
. - The Escape key was caught and bound callback/handler function (
quit
) invoked. But since it hasn't the required parameter (likeevent
) the invocation failed with aTypeError
.
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:
- The
<Enter>
event is when the mouse-pointer enters the (visible) widget frame, here of the application's root window. - 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
Python: Best Way to Add to Sys.Path Relative to the Current Running Script
High-Precision Clock in Python
Runtimeerror: Main Thread Is Not in Main Loop
How to Change the Figure Size with Subplots
How to Pass a User Defined Argument in Scrapy Spider
How to Run Pygame or Pyglet in a Browser
Python Script Returns Unintended "None" After Execution of a Function
No Module Named 'Polls.Apps.Pollsconfigdjango'; Django Project Tutorial 2
The Problem with Installing Pil Using Virtualenv or Buildout
Heapq with Custom Compare Predicate
Python's JSON Module, Converts Int Dictionary Keys to Strings
How to Do Assignments in a List Comprehension
How to Group a List of Tuples/Objects by Similar Index/Attribute in Python
Pil Thumbnail Is Rotating My Image
How to Check If Character in a String Is a Letter? (Python)
Can Existing Virtualenv Be Upgraded Gracefully
Is There a Description of How _Cmp_ Works for Dict Objects in Python 2
Take Screenshot of Full Page with Selenium Python with Chromedriver