Tastendruck in Python erkennen?

102

Ich mache ein Stoppuhr-Programm in Python und möchte wissen, wie man erkennt, ob eine Taste gedrückt wird (z. B. p für Pause und s für Stopp), und ich möchte nicht, dass es so etwas wie raw_input ist, das auf das wartet Benutzereingabe vor Fortsetzung der Ausführung. Weiß jemand, wie man das in einer while-Schleife macht?

Ich möchte diese Plattform auch plattformübergreifend gestalten, aber wenn dies nicht möglich ist, ist mein Hauptentwicklungsziel Linux

Lobuo
quelle
für OS X stackoverflow.com/a/47197390/5638869 funktioniert in Python 2 und 3
neoDev

Antworten:

65

Python verfügt über ein Tastaturmodul mit vielen Funktionen. Installieren Sie es, möglicherweise mit diesem Befehl:

pip3 install keyboard

Verwenden Sie es dann in Code wie:

import keyboard  # using module keyboard
while True:  # making a loop
    try:  # used try so that if user pressed other than the given key error will not be shown
        if keyboard.is_pressed('q'):  # if key 'q' is pressed 
            print('You Pressed A Key!')
            break  # finishing the loop
    except:
        break  # if user pressed a key other than the given key the loop will break
Gemeinschaft
quelle
1
Ich bin nicht sicher für Linux, aber es funktioniert unter Windows für mich.
69
keyboardanscheinend erfordert root in linux: /
Inaimathi
Ich habe diese Lösung ausprobiert, aber wenn ich versuche, das Modul nach der Installation zu importieren, wird "ImportError: Kein Modul mit dem Namen" Tastatur "" angezeigt, sodass es nicht funktioniert hat. Ich habe das GitHub-Repo eingecheckt und finde ein verwandtes Problem , aber es löst das Problem nicht. Dann habe ich versucht, das Repo herunterzuladen und einige seiner Beispiele auszuführen, aber ich erhalte "ImportError: Sie müssen root sein, um diese Bibliothek unter Linux zu verwenden", wie @Inaimathi zuvor kommentierte. Anscheinend scheint es ein volles Modul zu sein, um die Tastatur mit Python zu verwalten, aber die Anforderung von root ist ein großer Mangel :(
Ivanhercaz
3
"Um eine Abhängigkeit von X zu vermeiden, lesen die Linux-Teile unformatierte Gerätedateien (/ dev / input / input *), dies erfordert jedoch root."
Jrouquie
7
Ich verstehe nicht, warum der Versuch: außer: nützlich sein sollte.
TypicalHog
48

Für diejenigen, die an Fenstern stehen und Schwierigkeiten hatten, eine funktionierende Antwort zu finden, ist hier meine: 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()

Die obige Funktion druckt die Taste, die Sie drücken, und startet eine Aktion, wenn Sie die Esc-Taste loslassen. Die Tastaturdokumentation dient hier einer abwechslungsreicheren Verwendung.

Markus von Broady hob ein potenzielles Problem hervor: Diese Antwort erfordert nicht, dass Sie sich im aktuellen Fenster befinden, um dieses Skript zu aktivieren. Eine Lösung für Fenster wäre:

from win32gui import GetWindowText, GetForegroundWindow
current_window = (GetWindowText(GetForegroundWindow()))
desired_window_name = "Stopwatch" #Whatever the name of your window should be

#Infinite loops are dangerous.
while True: #Don't rely on this line of code too much and make sure to adapt this to your project.
    if current_window == desired_window_name:

        with Listener(
            on_press=on_press,
            on_release=on_release) as listener:
            listener.join()
Mitrek
quelle
7
@ nimig18 ... und benötigt kein root :)
cz
1
Bei dieser Lösung gibt es ein Problem (bei Alternativen nicht sicher): Die Taste muss nicht in einem Konsolenfenster gedrückt werden, damit sie wirksam wird. Stellen Sie sich vor, Sie haben ein Skript, das einige Aufgaben erledigt, bis ESC gedrückt wird, aber dann drücken Sie es in einem anderen Programm.
Markus von Broady
1
@MarkusvonBroady Ich denke, win32gui würde ausreichen, um es zu lösen. Ich habe meine Antwort so bearbeitet, dass sie möglicherweise zumindest für Windows-Benutzer gelöst werden kann.
Mitrek
@Mitrek Ich habe es versucht, aber mein Code stoppt die weitere Ausführung und steckt hier fest. Es funktioniert wie input (). Ich habe den Code in Selen ausgeführt, Firefox, aber sobald diese Sequenz angetroffen wird, gibt es keine weiteren Aktionen.
Lakshmi Narayanan
1
Sollte die akzeptierte Antwort gewesen sein, denn es funktioniert sowohl unter Linux als auch unter Windows
Akash Karnatak
31

Wie OP über raw_input erwähnt - das heißt, er möchte eine CLI-Lösung. Linux: Flüche ist das, was Sie wollen (Windows PDCurses). Curses ist eine grafische API für CLI-Software, mit der Sie mehr als nur Schlüsselereignisse erkennen können.

Dieser Code erkennt Tasten, bis eine neue Zeile gedrückt wird.

import curses
import os

def main(win):
    win.nodelay(True)
    key=""
    win.clear()                
    win.addstr("Detected key:")
    while 1:          
        try:                 
           key = win.getkey()         
           win.clear()                
           win.addstr("Detected key:")
           win.addstr(str(key)) 
           if key == os.linesep:
              break           
        except Exception as e:
           # No input   
           pass         

curses.wrapper(main)
Abc Xyz
quelle
Das ist wirklich schön. Musste für immer suchen, bevor ich darauf stieß. Scheint viel sauberer als herumzuhacken termiosund so weiter ...
Hugh Perkins
5
musste hinzugefügt import oswerden, um das Beispiel beenden zu können.
Malte
Wenn Sie dies win.nodelay(False)stattdessen tun True, werden keine Millionen Ausnahmen pro Sekunde generiert.
Johannes Hoff
24

Es gibt weitere Dinge, die mit dem keyboardModul erledigt werden können.

Hier sind einige der Methoden:


Methode 1:

Verwenden der Funktion read_key():

import keyboard

while True:
    if keyboard.read_key() == "p":
        print("You pressed p")
        break

Dies wird die Schleife unterbrechen, wenn die Taste pgedrückt wird.


Methode 2:

Funktion verwenden wait:

import keyboard

keyboard.wait("p")
print("You pressed p")

Es wartet darauf, dass Sie drücken, pund setzt den Code fort, während er gedrückt wird.


Methode 3:

Verwenden der Funktion on_press_key:

import keyboard

keyboard.on_press_key("p", lambda _:print("You pressed p"))

Es benötigt eine Rückruffunktion. Ich habe verwendet, _weil die Tastaturfunktion das Tastaturereignis an diese Funktion zurückgibt.

Nach der Ausführung wird die Funktion ausgeführt, wenn die Taste gedrückt wird. Sie können alle Hooks stoppen, indem Sie diese Zeile ausführen:

keyboard.unhook_all()

Methode 4:

Diese Methode wird bereits von user8167727 beantwortet, aber ich bin mit dem von ihnen erstellten Code nicht einverstanden. Es wird die Funktion verwenden, is_pressedaber auf andere Weise:

import keyboard

while True:
    if keyboard.is_pressed("p"):
        print("You pressed p")
        break

Es wird die Schleife brechen, wenn pgedrückt wird.


Anmerkungen:

  • keyboard liest Tastendrücke aus dem gesamten Betriebssystem.
  • keyboard erfordert root unter Linux
Schwarzer Donner
quelle
11
Das größte NEGATIVE bei der Verwendung von Tastaturmodulen ist die Anforderung, die Sie als ROOT-Benutzer ausführen. Dies macht das Modul in meinem Code verboten. Nur um abzufragen, ob eine Taste gedrückt wurde, sind keine Root-Rechte erforderlich. Ich habe das Dokument gelesen und verstehe, warum die Einschränkung im Modul
endet
Sehr hilfreiche Informationen geteilt, Sir! Ich wollte wissen, ob ich keyboard.wait()auf mehr als eine Taste warten und fortfahren kann, wenn eine von beiden gedrückt wird
Preetkaran Singh
@PreetkaranSingh wait()bietet diese Funktionalität nicht an. Sie müssen keyboard.read_key()mit einer if-Bedingung arbeiten, die in einer while-Schleife gepackt ist. Siehe die Methode # 1
Black Thunder
Vielen Dank, Sir!, Möchten Sie etwas Licht in die suppressVerwendung von Schlüsselwörtern bringen keyboard.read_key(), wann und wann nicht ...
Preetkaran Singh
@PreetkaranSingh Ich würde, aber ich habe nicht genug Informationen über das Unterdrückungsargument
Black Thunder
13

Für Windows könnten Sie Folgendes verwenden msvcrt:

   import msvcrt
   while True:
       if msvcrt.kbhit():
           key = msvcrt.getch()
           print(key)   # just to show the result
Benjie
quelle
7
msvcrt ist ein reines Windows-Modul.
Dunatotatos
1
Ich benutze jetzt tatsächlich Pynput, das könnte eine bessere Antwort sein
Benjie
Beachten Sie, dass pynput, um unter OS X zu funktionieren (ich weiß nichts über Linux), als root ausgeführt werden muss, um zu funktionieren. Das kann für einige Leute ein Nichtstarter sein.
Gabe Weiss
Ich hätte schwören können, dass die Frage nach "plattformübergreifend" oder "Linux" war ...
Aaron Mann
10

Verwenden Sie diesen Code, um herauszufinden, welche Taste gedrückt wurde

from pynput import keyboard

def on_press(key):
    try:
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:
        print('special key {0} pressed'.format(
            key))

def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.esc:
        # Stop listener
        return False

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()
Manivannan Murugavel
quelle
Hier ist die Sache, ich benutze macOS und installiere sowohl Pynput als auch Tastatur getrennt, und das Programm läuft fehlerfrei, kann aber nur (auf der Python-Shell) Sondertasten erkennen. Alphanumerische Schlüssel werden nicht erkannt und im Gegenteil so betrachtet, als würde ich Code auf die Shell schreiben. Wissen Sie, woran es liegen könnte?
Dario Deniz Ergün
Der gleiche Code funktionierte für mich in der Shell. Überprüfen Sie bitte das. Das Tastaturpaket benötigt diesen Code nicht.
Manivannan Murugavel
1
Dies ist der Weg unter Linux, da die Tastaturbibliothek root benötigt.
David
1
Diese Lösung erkennt alle Tastenanschläge. auch solche, die in einem anderen Terminalfenster passieren. Leider schränkt dies die möglichen Anwendungsfälle stark ein.
Serge Stroobandt
6

Verwenden Sie PyGame, um ein Fenster zu haben, und dann können Sie die wichtigsten Ereignisse abrufen.

Für den Brief p:

import pygame, sys
import pygame.locals

pygame.init()
BLACK = (0,0,0)
WIDTH = 1280
HEIGHT = 1024
windowSurface = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)

windowSurface.fill(BLACK)

while True:
    for event in pygame.event.get():
        if event.key == pygame.K_p: # replace the 'p' to whatever key you wanted to be pressed
             pass #Do what you want to here
        if event.type == pygame.locals.QUIT:
             pygame.quit()
             sys.exit()
AJ Uppal
quelle
2

Also habe ich dieses ..kind of game .. basierend auf diesem Beitrag gemacht (mit msvcr library und Python 3.7).

Das Folgende ist die "Hauptfunktion" des Spiels, die das Drücken der gedrückten Tasten erkennt:

# Requiered libraries - - - -
import msvcrt
# - - - - - - - - - - - - - -


def _secret_key(self):
    # Get the key pressed by the user and check if he/she wins.

    bk = chr(10) + "-"*25 + chr(10)

    while True:

        print(bk + "Press any key(s)" + bk)
        #asks the user to type any key(s)

        kp = str(msvcrt.getch()).replace("b'", "").replace("'", "")
        # Store key's value.

        if r'\xe0' in kp:
            kp += str(msvcrt.getch()).replace("b'", "").replace("'", "")
            # Refactor the variable in case of multi press.

        if kp == r'\xe0\x8a':
            # If user pressed the secret key, the game ends.
            # \x8a is CTRL+F12, that's the secret key.

            print(bk + "CONGRATULATIONS YOU PRESSED THE SECRET KEYS!\a" + bk)
            print("Press any key to exit the game")
            msvcrt.getch()
            break
        else:
            print("    You pressed:'", kp + "', that's not the secret key(s)\n")
            if self.select_continue() == "n":
                if self.secondary_options():
                    self._main_menu()
                break

Wenn Sie den vollständigen Quellcode des Porgramms möchten, können Sie ihn sehen oder von hier herunterladen:

Das geheime Schlüsselspiel (GitHub)

(Hinweis: Der geheime Tastendruck lautet: Ctrl+ F12)

Ich hoffe, Sie können als Beispiel und Hilfe für diejenigen dienen, die diese Informationen konsultieren.

Ferd
quelle
1
key = cv2.waitKey(1)

Dies ist aus dem openCV-Paket. Es erkennt einen Tastendruck ohne zu warten.

eyllanesc
quelle