Python >> Tutoriel Python >  >> Python Tag >> Linux

Comment activer la détection des touches sur un terminal Linux, style bas niveau en python

Par défaut, l'entrée standard est mise en mémoire tampon et utilise le mode canonique. Cela vous permet de modifier votre entrée. Lorsque vous appuyez sur la touche Entrée, l'entrée peut être lue par Python.

Si vous souhaitez un accès de niveau inférieur à l'entrée, vous pouvez utiliser tty.setraw() sur le descripteur de fichier d'entrée standard. Cela vous permet de lire un caractère à la fois en utilisant sys.stdin.read(1) . Notez que dans ce cas, le script Python sera responsable de la gestion des caractères spéciaux et vous perdrez certaines fonctionnalités telles que l'écho et la suppression de caractères. Pour plus d'informations, consultez termios(3).

Vous pouvez en savoir plus sur les séquences d'échappement utilisées pour les touches haut et bas sur Wikipedia.

Vous devriez être en mesure de reproduire le comportement standard du shell si vous gérez tout en un seul processus.

Vous pouvez également essayer d'utiliser un sous-processus (ne faisant pas référence au module - vous pouvez utiliser fork() ou popen() ). Vous analyseriez l'entrée non tamponnée dans le processus principal et l'enverriez à stdin (qui peut être mis en mémoire tampon) du sous-processus. Vous aurez probablement besoin d'avoir une communication inter-processus pour partager l'historique avec le processus principal.

Voici un exemple du code nécessaire pour capturer l'entrée de cette façon. Notez qu'il n'effectue qu'un traitement de base et nécessite plus de travail pour s'adapter à votre cas d'utilisation.

import sys
import tty
import termios


def getchar():
    fd = sys.stdin.fileno()
    attr = termios.tcgetattr(fd)
    try:
        tty.setraw(fd)
        return sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSANOW, attr)


EOT = '\x04'  # CTRL+D
ESC = '\x1b'
CSI = '['

line = ''

while True:
    c = getchar()
    if c == EOT:
        print('exit')
        break
    elif c == ESC:
        if getchar() == CSI:
            x = getchar()
            if x == 'A':
                print('UP')
            elif x == 'B':
                print('DOWN')
    elif c == '\r':
        print([line])
        line = ''
    else:
        line += c

Python a un module clavier avec de nombreuses fonctionnalités. Installez-le, peut-être avec cette commande :

pip install keyboard

puis utilisez-le dans un code comme celui-ci :

import keyboard

keyboard.add_hotkey('up', lambda: keyboard.write('write command retrieved from the history of your shell here'))
keyboard.wait('esc')

ou vous pouvez utiliser la fonction on_press_keyUtiliser la fonction on_press_key :

keyboard.on_press_key("p", lambda _:print("You pressed p"))

Il a besoin d'une fonction de rappel. J'ai utilisé _ car la fonction clavier renvoie l'événement clavier à cette fonction.

Une fois exécuté, il exécutera la fonction lorsque la touche sera enfoncée. Vous pouvez arrêter tous les hooks en exécutant cette ligne :

keyboard.unhook_all()

pour des informations détaillées, vous pouvez voir un article similaire sur stackoverflow, espérons que cela aide à détecter la pression sur la touche en python ?

Sur le côté Remarque : vous avez mentionné la méthode fork() ci-dessus En python, nous pouvons utiliser le

sous-processus module intégré ici, alors importez le sous-processus et nous sommes prêts à partir. La fonction run en particulier est utilisée ici pour exécuter des commandes dans un sous-shell. Pour ceux qui viennent de C, cela nous évite de créer un processus enfant et d'attendre que l'enfant termine son exécution, laissez Python s'en occuper cette fois-ci.

exemple de code pour exécuter les commandes saisies par l'utilisateur

def execute_commands(command):
    try:
        subprocess.run(command.split())
    except Exception:
        print("psh: command not found: {}".format(command))