La lecture d'un seul caractère (style getch) en Python ne fonctionne pas sous Unix

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

  •  20-08-2019
  •  | 
  •  

Question

Chaque fois que j'utilise la recette sur http://code.activestate.com/recipes/134892 / Je n'arrive pas à le faire fonctionner. Il génère toujours l'erreur suivante:

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

Ma meilleure pensée, c’est que c’est parce que je l’exécute dans Eclipse, de sorte que termios jette un doute sur le descripteur de fichier.

Était-ce utile?

La solution

Cela fonctionne sur Ubuntu 8.04.1, Python 2.5.2, je n’obtiens aucune erreur de ce type. Peut-être devriez-vous essayer à partir de la ligne de commande, eclipse peut utiliser son propre stdin, je reçois exactement la même erreur si je le lance à partir de Wing IDE, mais à partir de la ligne de commande, il fonctionne très bien. La raison est que IDE, par exemple Wing, utilise sa propre classe netserver.CDbgInputStream en tant que sys.stdin alors sys.stdin.fileno vaut zéro, c’est pourquoi l’erreur. En gros, IDE stdin n’est pas un tty (print sys.stdin.isatty () est 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()

Autres conseils

Mettre le terminal en mode brut n’est pas toujours une bonne idée. En fait, il suffit d'effacer le bit ICANON. Voici une autre version de getch () avec prise en charge de l'expiration du délai d'attente:

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()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top