Abfragen der Tastatur (Erkennen eines Tastendrucks) in Python

Lesezeit: 6 Minuten

Abfragen der Tastatur Erkennen eines Tastendrucks in Python
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

Abfragen der Tastatur Erkennen eines Tastendrucks in Python
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

1643950568 943 Abfragen der Tastatur Erkennen eines Tastendrucks in Python
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.

https://pypi.python.org/pypi/pynput

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

    – Markieren

    31. Dezember 17 um 21:29 Uhr

Abfragen der Tastatur Erkennen eines Tastendrucks in Python
jfs

Aus den Kommentaren:

import msvcrt # built-in module

def kbfunc():
    return ord(msvcrt.getch()) if msvcrt.kbhit() else 0

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

1643950568 764 Abfragen der Tastatur Erkennen eines Tastendrucks in Python
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

.

764740cookie-checkAbfragen der Tastatur (Erkennen eines Tastendrucks) in Python

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy