Sprawdzanie klawiatury (wykrywanie klawiatury) w Pythonie

Jak mogę sprawdzić klawiaturę z konsolowej aplikacji Pythona? W szczególności, chciałbym zrobić coś podobnego do tego w pośród wielu innych działań we/wy (wybór gniazda, dostęp do portu szeregowego, itp.):

   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

Jaki jest prawidłowy sposób, aby to zrobić w systemie Windows? Ponadto, przenośność do Linuksa nie byłaby zła, choć nie jest wymagana.

Author: alexis, 2008-11-15

9 answers

Standardowym podejściem jest użycie modułu select .

Jednak to nie działa na Windows. W tym celu możesz użyć klawiatury modułu msvcrt .

Często odbywa się to z wieloma wątkami - po jednym na każde urządzenie jest "obserwowany" oraz procesami w tle, które mogą wymagać przerwania przez urządzenie.

 28
Author: S.Lott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-17 09:54:34

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
 17
Author: tsvikas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-19 14:23:32

Ok, ponieważ moja próba umieszczenia mojego rozwiązania w komentarzu nie powiodła się, oto co chciałem powiedzieć. Mogłem zrobić dokładnie to, co chciałem z natywnego Pythona (w systemie Windows, a nie gdziekolwiek indziej) za pomocą następującego kodu:

import msvcrt 

def kbfunc(): 
   x = msvcrt.kbhit()
   if x: 
      ret = ord(msvcrt.getch()) 
   else: 
      ret = 0 
   return ret
 14
Author: K. Brafford,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-20 00:32:05

Rozwiązanie wykorzystujące moduł curses. Drukowanie wartości liczbowej odpowiadającej każdemu wciśniętemu klawiszowi:

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)
 13
Author: W. Russell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-18 15:48:39

Żadna z tych odpowiedzi nie zadziałała dobrze dla mnie. Ten pakiet, pynput, robi dokładnie to, czego potrzebuję.

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()
 10
Author: wroscoe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-11 06:31:18

Możesz zobaczyć, jak pygame radzi sobie z tym, aby ukraść kilka pomysłów.

 5
Author: Rizwan Kassim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-15 03:49:45

Z komentarzy:

import msvcrt # built-in module

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

Dzięki za pomoc. Skończyło się na napisaniu C DLL o nazwie PyKeyboardAccess.dll i uzyskiwanie dostępu do funkcji crt conio, eksportowanie tej procedury:
#include <conio.h>

int kb_inkey () {
   int rc;
   int key;

   key = _kbhit();

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

   return rc;
}

I uzyskuję do niego dostęp w Pythonie za pomocą modułu ctypes (wbudowanego w Pythona 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)
 5
Author: K. Brafford,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-16 17:48:25

Jeśli połączysz czas.śpij, gwintuj.Wątek i sys.stdin.odczyt można z łatwością odczekać określoną ilość czasu na wejście, a następnie kontynuować, powinno to być również kompatybilne z wieloma platformami.

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

Można również umieścić to w Funkcji Tak

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

Chociaż to nie zwróci niczego, więc zamiast tego powinieneś użyć modułu multiprocessing pool, możesz znaleźć to tutaj: Jak uzyskać wartość zwracaną z wątku w Pythonie?

 0
Author: chbchb55,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:50

Używam tego do sprawdzania naciśnięć klawiszy, nie może być dużo prostsze:

#!/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)

Podczas gdy curses nie działa na windows, istnieje wersja 'unicurses', podobno działa na Linuksie, Windows, Mac, ale nie mogłem tego uruchomić

 0
Author: ullix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-19 15:34:29