Leggere un singolo personaggio (stile getch) in Python non funziona in Unix

StackOverflow https://stackoverflow.com/questions/1052107

  •  20-08-2019
  •  | 
  •  

Domanda

Ogni volta che utilizzo la ricetta su http://code.activestate.com/recipes/134892 / Non riesco a farlo funzionare. Genera sempre il seguente errore:

Traceback (most recent call last):
    ...
    old_settings = termios.tcgetattr(fd)
termios.error: (22, 'Invalid argument)

La mia migliore idea è che lo sia perché lo sto eseguendo in Eclipse, quindi termios si sta adattando al descrittore di file.

È stato utile?

Soluzione

Funziona su Ubuntu 8.04.1, Python 2.5.2, non ricevo questo errore. Forse dovresti provarlo dalla riga di comando, eclipse potrebbe usare il suo stesso stdin, ottengo lo stesso errore esatto se lo eseguo da Wing IDE, ma dalla riga di comando funziona alla grande. Il motivo è che IDE, ad esempio Wing, utilizza la propria classe netserver.CDbgInputStream come sys.stdin quindi sys.stdin.fileno è zero, ecco perché l'errore. Fondamentalmente IDE stdin non è un tty (print sys.stdin.isatty () is False)

class _GetchUnix:
    def __init__(self):
        import tty, sys

    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch


getch = _GetchUnix()

print getch()

Altri suggerimenti

Mettere il terminale in modalità raw non è sempre una buona idea. In realtà è sufficiente cancellare bit ICANON. Ecco un'altra versione di getch () con supporto timeout:

import tty, sys, termios
import select

def setup_term(fd, when=termios.TCSAFLUSH):
    mode = termios.tcgetattr(fd)
    mode[tty.LFLAG] = mode[tty.LFLAG] & ~(termios.ECHO | termios.ICANON)
    termios.tcsetattr(fd, when, mode)

def getch(timeout=None):
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        setup_term(fd)
        try:
            rw, wl, xl = select.select([fd], [], [], timeout)
        except select.error:
            return
        if rw:
            return sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)

if __name__ == "__main__":
    print getch()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top