2015-12-28 10 views
8

In questo momento sto provando a fare un piccolo codice con un lampone pi e un makey. Il makey fay è una piccola scheda che funziona come una tastiera USB quando alcuni contatti sono alimentati. La mia domanda è qual è il modo più semplice per rilevare quei tasti premuti all'interno di uno script python. Capisco che usare i pin GPIO sarebbe più facile, ma ora sto cercando questo. Ho visto esempi come usare l'uso di getch() da msvcrt (che da quello che capisco è solo Windows), usando pygame.key e usando getKey. Quale di queste tesi è più facile da usare? Ce n'è qualcuno in grado di rilevare la pressione di un tasto e il rilascio di un tasto?Qual è il modo più semplice per rilevare le pressioni dei tasti in python 3 su una macchina Linux?

Pseudocodice codice (... è che come si chiama?)

import whatever needs importing  

if the "W" key is pressed: 
    print ("You pressed W") 

elif the "S" is pressed: 
    print ("You pressed S") 

e così via. Grazie.

+0

si potrebbe verificare interfacce grafiche con associazioni di tasti vedere tk: https://docs.python.org/3/library/tk.html – LittleByBlue

risposta

9

Questo è un ciclo semplice che inserisce lo stdin in modalità raw (disabilitando il buffering in modo da non dover premere invio) per ottenere singoli caratteri. Si dovrebbe fare qualcosa di più intelligente (come una dichiarazione with per disabilitarlo), ma si ottiene l'idea qui:

import tty 
import sys 
import termios 

orig_settings = termios.tcgetattr(sys.stdin) 

tty.setraw(sys.stdin) 
x = 0 
while x != chr(27): # ESC 
    x=sys.stdin.read(1)[0] 
    print("You pressed", x) 

termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings)  

penso che avrei dovuto loop per rilevare rilasci chiave in Python.

ETA po 'di spiegazione:

Su Linux, in ingresso al vostro programma sarà linea tamponato. Ciò significa che il sistema operativo bufferizzerà l'input fino a quando non avrà un'intera riga, quindi il tuo programma non vedrà nemmeno nulla che l'utente abbia digitato fino a quando l'utente non preme anche "invio". In altre parole, se il tuo programma si aspetta che l'utente digiti "w" e l'utente lo faccia, "w" si troverà nel buffer del sistema operativo fino a quando l'utente non farà clic su "invio". A questo punto l'intera riga viene consegnata al tuo programma in modo da ottenere la stringa "w \ n" come input dell'utente.

È possibile disattivare questo mettendo il tty in modalità raw. Lo fai con la funzione Python tty.setraw che effettuerà una chiamata verso il basso del driver tty in linux per dirgli di smettere di buffering. Ho passato l'argomento sys.stdin per dirgli quale stream volevo disattivare il buffering per . Quindi, dopo la chiamata tty.setraw, il ciclo sopra ti darà l'output per ogni tasto che l'utente preme.

Una complicazione, tuttavia, è che una volta terminato il programma, la tty è ancora in modalità raw.Generalmente questo è insoddisfacente dal momento che non si ottiene la potenza offerta dalle impostazioni dei terminali moderni (come quando si usano sequenze di controllo o di escape). Ad esempio, noterai che potresti avere problemi ad uscire dal programma con ctrl-C. Di conseguenza è necessario reinserire il terminale nella modalità cessa dopo aver letto i caratteri di input. La chiamata termios.tcsetattr dice semplicemente "rimetti il ​​terminale nel modo in cui l'ho trovato". Sa come farlo chiamando in primo luogo termios.tcgetattr all'inizio del programma che sta dicendo "dimmi tutte le impostazioni correnti per il terminale".

Una volta compreso tutto, dovresti essere in grado di incapsulare la funzionalità in una funzione adatta al tuo programma.

stdin è lo stream che l'input proviene all'utente. Wikipedia può dirti di più su standard streams.

+0

carina. molto utile in molte altre situazioni, anche – LittleByBlue

+0

Sembra che questo sia quello che voglio usare, (ha funzionato meravigliosamente sul pi,) ma non sono chiaro esattamente cosa sto facendo. Conoscete qualche documentazione amichevole di noob su questo? Potresti abbattere il tuo codice o mostrarmi come usarlo in una dichiarazione if? – montainz09

+0

@ montainz09 Ho aggiunto qualche altra spiegazione. Spero che aiuti. – Turn

8

Utilizzando un buon modulo leggero curtsies si potrebbe fare qualcosa di simile (tratto dal loro examples /):

from curtsies import Input 

def main(): 
    with Input(keynames='curses') as input_generator: 
     for e in input_generator: 
      print(repr(e)) 

if __name__ == '__main__': 
    main() 

Quindi premendo i tasti sulla tastiera ti dà qualcosa di simile:

'a' 
's' 
'KEY_F(1)' 
'KEY_F(2)' 
'KEY_F(3)' 
'KEY_F(4)' 
'KEY_F(5)' 
'KEY_LEFT' 
'KEY_DOWN' 
'KEY_UP' 
'KEY_RIGHT' 
'KEY_NPAGE' 
'\n' 

curtsies è utilizzato da bpython come astrazione di basso livello di materiale relativo ai terminali.

Il problema di base della decodifica dell'input è che in diversi terminali e programmi di emulazione di terminale come xterm o gnome-terminals fisicamente stessi tasti producono sequenze di codici di tasti differenti. Ecco perché è necessario sapere quali impostazioni del terminale devono essere utilizzate per decodificare l'input. Tale modulo aiuta ad astrarre da quei dettagli cruenti.

+0

Questa soluzione è la migliore per me perché gestisce 'KEY_UP' (tra gli altri) mentre la risposta accettata non è – vinzee