Abfragen der Tastatur (Erkennen eines Tastendrucks) in Python
Lesezeit: 6 Minuten
K. Brafford
Wie kann ich die Tastatur von einer Konsolen-Python-App aus abfragen? Insbesondere möchte ich inmitten vieler anderer E / A-Aktivitäten (Socket-Auswahl, Zugriff auf serielle Ports usw.) etwas Ähnliches tun:
while 1:
# doing amazing pythonic embedded stuff
# ...
# periodically do a non-blocking check to see if
# we are being told to do something else
x = keyboard.read(1000, timeout = 0)
if len(x):
# ok, some key got pressed
# do something
Was ist der richtige pythonische Weg, dies unter Windows zu tun? Außerdem wäre die Portabilität auf Linux nicht schlecht, obwohl dies nicht erforderlich ist.
Nur um andere Leute wissen zu lassen, ich habe festgestellt, dass die meisten Lösungen mit Auswahl- oder Thread-Bibliotheken von IDLE aus nicht richtig funktionierten. Allerdings sie alle funktionierte gut auf der CLI dh python /home/pi/poll_keyboard.py
– Davidschaft2
19. Oktober 16 um 11:18 Uhr
Im Allgemeinen denke ich, dass das Reagieren auf Tastendrücke, anstatt sie regelmäßig abzufragen, eine robustere Lösung ist, da Sie die Tastendrücke möglicherweise nicht verpassen. Siehe meine Antwort unten.
– ilon
27. Oktober 21 um 15:28 Uhr
S. Lott
Der Standardansatz ist die Verwendung von wählen Modul.
Dies funktioniert jedoch nicht unter Windows. Dafür können Sie die verwenden msvcrt Tastaturabfrage des Moduls.
Häufig geschieht dies mit mehreren Threads – einem pro überwachtem Gerät plus den Hintergrundprozessen, die möglicherweise vom Gerät unterbrochen werden müssen.
Korrigieren Sie mich, wenn ich falsch liege, aber meiner Erfahrung nach funktioniert msvcrt nur, wenn Sie das Programm in einem Befehlsfenster ausführen, dh. nicht im IDLE und nicht mit einer GUI …
– Darth Vlader
24. Juni 18 um 08:14 Uhr
@digitalHamster0: Alles, was ersetzt sys.stdin mit einem benutzerdefinierten Objekt (zB IDLE, die meisten GUIs) würde diesen Effekt haben. Wann sys.stdin ist keine echte Datei, die Sie nicht verwenden können select; Wenn es nicht mit einer “echten” Konsole verbunden ist, können Sie die nicht verwenden msvcrt Tastaturabfragefunktionen (die sich implizit auf eine “echte” Konsole stützen).
– ShadowRanger
29. August 18 um 15:52 Uhr
Im Allgemeinen denke ich, dass das Reagieren auf Tastendrücke, anstatt sie regelmäßig abzufragen, eine robustere Lösung ist, da Sie die Tastendrücke möglicherweise nicht verpassen. Siehe meine Antwort unten.
– ilon
27. Oktober 21 um 15:27 Uhr
W.Russell
Eine Lösung mit dem Curses-Modul. Drucken eines numerischen Werts entsprechend jeder gedrückten Taste:
import curses
def main(stdscr):
# do not wait for input when calling getch
stdscr.nodelay(1)
while True:
# get keyboard input, returns -1 if none available
c = stdscr.getch()
if c != -1:
# print numeric value
stdscr.addstr(str(c) + ' ')
stdscr.refresh()
# return curser to start position
stdscr.move(0, 0)
if __name__ == '__main__':
curses.wrapper(main)
OZ123: Kann es. Siehe stackoverflow.com/questions/32417379/…
– Joshua Clayton
25. Mai ’16 um 18:47 Uhr
Hatte Probleme bei der Verwendung von Flüchen über den SSH-Begriff auf einem Headless-Host. Probleme haben das Terminal stark durcheinander gebracht – was es erforderte reset zwischen jedem Lauf. Es hat funktioniert, dh Tastendruck erkennen. Es muss eine intelligentere Lösung geben.
– Markieren
31. Dezember 17 um 21:31 Uhr
Ok, da mein Versuch, meine Lösung in einem Kommentar zu posten, fehlgeschlagen ist, wollte ich Folgendes sagen. Ich konnte mit dem folgenden Code genau das tun, was ich von nativem Python wollte (unter Windows, nirgendwo anders):
import msvcrt
def kbfunc():
x = msvcrt.kbhit()
if x:
ret = ord(msvcrt.getch())
else:
ret = 0
return ret
import sys
import select
def heardEnter():
i,o,e = select.select([sys.stdin],[],[],0.0001)
for s in i:
if s == sys.stdin:
input = sys.stdin.readline()
return True
return False
Keine dieser Antworten funktionierte gut für mich. Dieses Paket, pynput, macht genau das, was ich brauche.
from pynput.keyboard import Key, Listener
def on_press(key):
print('{0} pressed'.format(
key))
def on_release(key):
print('{0} release'.format(
key))
if key == Key.esc:
# Stop listener
return False
# Collect events until released
with Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
Dies funktionierte für mich, außer dass die gedrückte Taste sofort nach dem Drücken auf dem Bildschirm wiedergegeben wurde und es keine Möglichkeit gab, sie zu deaktivieren. github.com/moses-palmer/pynput/issues/47 Außerdem werden die Zeichen gepuffert und erscheinen zusätzlich auf der Befehlszeile, wenn das Programm beendet wird. Dies scheint eine Einschränkung der Linux-Implementierung zu sein, aber es funktioniert gut unter Windows.
– Trevor
6. September 17 um 2:35 Uhr
Diese Lösung funktioniert nicht, wenn das Skript über ssh ausgeführt wird. Es bombardiert mit dem Fehler: ‘Xlib.error.DisplayNameError: Bad display name “”.’
– David Stein
19. November 17 um 4:05 Uhr
Wie oben von David erwähnt, ist dies keine gute Lösung für Headless-Instanzen, da es eine Abhängigkeit von Xserver hat. import Xlib.display
Danke für die Hilfe. Am Ende habe ich eine C-DLL namens PyKeyboardAccess.dll geschrieben und auf die crt conio-Funktionen zugegriffen, indem ich diese Routine exportiert habe:
#include <conio.h>
int kb_inkey () {
int rc;
int key;
key = _kbhit();
if (key == 0) {
rc = 0;
} else {
rc = _getch();
}
return rc;
}
Und ich greife in Python mit dem ctypes-Modul (eingebaut in Python 2.5) darauf zu:
import ctypes
import time
#
# first, load the DLL
#
try:
kblib = ctypes.CDLL("PyKeyboardAccess.dll")
except:
raise ("Error Loading PyKeyboardAccess.dll")
#
# now, find our function
#
try:
kbfunc = kblib.kb_inkey
except:
raise ("Could not find the kb_inkey function in the dll!")
#
# Ok, now let's demo the capability
#
while 1:
x = kbfunc()
if x != 0:
print "Got key: %d" % x
else:
time.sleep(.01)
Dies funktionierte für mich, außer dass die gedrückte Taste sofort nach dem Drücken auf dem Bildschirm wiedergegeben wurde und es keine Möglichkeit gab, sie zu deaktivieren. github.com/moses-palmer/pynput/issues/47 Außerdem werden die Zeichen gepuffert und erscheinen zusätzlich auf der Befehlszeile, wenn das Programm beendet wird. Dies scheint eine Einschränkung der Linux-Implementierung zu sein, aber es funktioniert gut unter Windows.
– Trevor
6. September 17 um 2:35 Uhr
Diese Lösung funktioniert nicht, wenn das Skript über ssh ausgeführt wird. Es bombardiert mit dem Fehler: ‘Xlib.error.DisplayNameError: Bad display name “”.’
– David Stein
19. November 17 um 4:05 Uhr
Wie oben von David erwähnt, ist dies keine gute Lösung für Headless-Instanzen, da es eine Abhängigkeit von Xserver hat. import Xlib.display
– Markieren
31. Dezember 17 um 21:29 Uhr
ivan_pozdeev
Ich bin auf eine plattformübergreifende Implementierung von gestoßen kbhit beim http://home.wlu.edu/~levys/software/kbhit.py (Änderungen vorgenommen, um irrelevanten Code zu entfernen):
import os
if os.name == 'nt':
import msvcrt
else:
import sys, select
def kbhit():
''' Returns True if a keypress is waiting to be read in stdin, False otherwise.
'''
if os.name == 'nt':
return msvcrt.kbhit()
else:
dr,dw,de = select.select([sys.stdin], [], [], 0)
return dr != []
Stellen Sie sicher, dass read() das/die wartende(n) Zeichen – die Funktion kehrt immer wieder zurück True bis du es tust!
Ist das noch aktuell? Wenn ich die ausgewählte Version aufrufe, bekomme ich immer wieder Inhalte in dr. Wenn es immer noch funktioniert, können Sie es in einen Kontext stellen? Ich habe eine “while true”-Schleife, aus der ich aussteigen möchte, wenn eine Taste gedrückt wird.
– Dogge
8. Juni 21 um 19:11 Uhr
@Mastiff vielleicht nicht read() die wartenden Zeichen, nachdem sie wie empfohlen erkannt wurden.
– ivan_pozdeev
8. Juni 21 um 23:34 Uhr
.
7647400cookie-checkAbfragen der Tastatur (Erkennen eines Tastendrucks) in Pythonyes
Nur um andere Leute wissen zu lassen, ich habe festgestellt, dass die meisten Lösungen mit Auswahl- oder Thread-Bibliotheken von IDLE aus nicht richtig funktionierten. Allerdings sie alle funktionierte gut auf der CLI dh
python /home/pi/poll_keyboard.py
– Davidschaft2
19. Oktober 16 um 11:18 Uhr
Im Allgemeinen denke ich, dass das Reagieren auf Tastendrücke, anstatt sie regelmäßig abzufragen, eine robustere Lösung ist, da Sie die Tastendrücke möglicherweise nicht verpassen. Siehe meine Antwort unten.
– ilon
27. Oktober 21 um 15:28 Uhr