Frage

Wie kann ich die Tastatur von einer Konsole Python App abfragen? Insbesondere möchte ich so etwas wie dies in der Mitte von vielen anderen E / A-Aktivitäten tun (Buchse wählt, seriellen Port, etc.):

   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 Weg, dies pythonic auf Windows zu tun? Auch Portierbarkeit auf Linux wäre nicht schlecht, obwohl es nicht erforderlich ist.

War es hilfreich?

Lösung

Der Standardansatz ist die Modul auswählen.

Dies ist jedoch nicht funktioniert unter Windows. Dafür können Sie die msvcrt Moduls Tastatur Polling.

Oft wird dies mit mehreren Threads getan - ein pro Gerät „beobachtet“ werden und die Hintergrundprozesse, die vom Gerät unterbrochen müssen möglicherweise werden

.

Andere Tipps


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

Eine Lösung, die Flüche Modul. einen numerischen Wert Drucken auf jeder Taste entspricht gedrückt:

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)

Ok, da mein Versuch, meine Lösung in einem Kommentar zu schreiben versagt, hier ist was ich versucht habe zu sagen. Ich konnte tun genau das, was ich aus nativen Python (unter Windows, nirgendwo sonst aber) mit dem folgenden Code gesucht:

import msvcrt 

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

Keine dieser Antworten war für mich gut. Dieses Paket, pynput, tut 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()

Sie können sehen, wie pygame behandelt dies einige Ideen zu stehlen.

Aus den Kommentaren:

import msvcrt # built-in module

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

Danke für die Hilfe. Ich landete mit einem C-DLL zu schreiben genannt PyKeyboardAccess.dll und die crt conio Funktionen Zugriff, exportieren diese Routine:

#include <conio.h>

int kb_inkey () {
   int rc;
   int key;

   key = _kbhit();

   if (key == 0) {
      rc = 0;
   } else {
      rc = _getch();
   }

   return rc;
}

Und ich zugreifen es in Python des ctypes Modul (eingebaut in Python 2.5):

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)

ich dies für Tastendrücke für die Überprüfung verwende, kann nicht viel einfacher:

#!/usr/bin/python3
# -*- coding: UTF-8 -*-

import curses, time

def main(stdscr):
    """checking for keypress"""
    stdscr.nodelay(True)  # do not wait for input when calling getch
    return stdscr.getch()

while True:
    print("key:", curses.wrapper(main)) # prints: 'key: 97' for 'a' pressed
                                        # '-1' on no presses
    time.sleep(1)

Während Flüche nicht auf Windows arbeiten, gibt es eine ‚unicurses‘ -Version, angeblich arbeiten an Linux, Windows, Mac, aber ich konnte nicht das

arbeiten

Ich habe über eine plattformübergreifende Implementierung von kbhit kommen unter http: / /home.wlu.edu/~levys/software/kbhit.py (vorgenommenen Änderungen irrelevant 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 != []

Achten Sie auf die Wartezeichen (s) read() - die Funktion hält True zurückkehren, bis Sie tun

Wenn Sie kombinieren time.sleep, threading.Thread und sys.stdin.read Sie leicht für eine bestimmte Menge an Zeit für die Eingabe warten und dann weiter, auch sollte diese Cross-Plattform kompatibel ist.

t = threading.Thread(target=sys.stdin.read(1) args=(1,))
t.start()
time.sleep(5)
t.join()

Sie können auch diese in eine Funktion setzen wie so

def timed_getch(self, bytes=1, timeout=1):
    t = threading.Thread(target=sys.stdin.read, args=(bytes,))
    t.start()
    time.sleep(timeout)
    t.join()
    del t

Obwohl dies nichts zurück, um stattdessen sollten Sie den Multiprocessing-Pool-Modul verwenden Sie können das hier finden: , wie den Rückgabewert von einem Thread in python bekommen?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top