De forma predeterminada, la entrada estándar se almacena en búfer y utiliza el modo canónico. Esto le permite editar su entrada. Cuando presiona la tecla Intro, Python puede leer la entrada.
Si desea un acceso de nivel inferior a la entrada, puede usar tty.setraw()
en el descriptor de archivo de entrada estándar. Esto le permite leer un carácter a la vez usando sys.stdin.read(1)
. Tenga en cuenta que, en este caso, la secuencia de comandos de Python será responsable de manejar los caracteres especiales y perderá algunas de las funciones, como el eco y la eliminación de caracteres. Para obtener más información, consulte termios(3).
Puede leer sobre las secuencias de escape que se utilizan para las teclas arriba y abajo en Wikipedia.
Debería poder replicar el comportamiento estándar del shell si maneja todo en un solo proceso.
También puede intentar usar un subproceso (sin referirse al módulo; puede usar fork()
o popen()
). Analizaría la entrada sin búfer en el proceso principal y la enviaría a la entrada estándar (que se puede almacenar en búfer) del subproceso. Probablemente necesitará tener alguna comunicación entre procesos para compartir el historial con el proceso principal.
Aquí hay un ejemplo del código necesario para capturar la entrada de esta manera. Tenga en cuenta que solo está realizando un procesamiento básico y necesita más trabajo para adaptarse a su caso de uso.
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 tiene un módulo de teclado con muchas funciones. Instálalo, quizás con este comando:
pip install keyboard
luego utilícelo en un código como este:
import keyboard
keyboard.add_hotkey('up', lambda: keyboard.write('write command retrieved from the history of your shell here'))
keyboard.wait('esc')
o puede usar la función on_press_keyUsing the function on_press_key:
keyboard.on_press_key("p", lambda _:print("You pressed p"))
Necesita una función de devolución de llamada. Usé _ porque la función del teclado devuelve el evento del teclado a esa función.
Una vez ejecutado, ejecutará la función cuando se presione la tecla. Puede detener todos los ganchos ejecutando esta línea:
keyboard.unhook_all()
para obtener información detallada, puede ver una publicación similar en stackoverflow, ¿espero que esto ayude a detectar la pulsación de tecla en python?
Nota lateral: mencionaste el método fork() arriba En Python podemos usar el
subproceso módulo incorporado aquí, así que importe el subproceso y estamos listos para comenzar. La función de ejecución en particular se usa aquí para ejecutar comandos en una subcapa. Para aquellos que vienen de C, esto nos evita tener que bifurcar y crear un proceso hijo y luego esperar a que el hijo termine de ejecutarse, dejemos que Python se encargue de eso esta vez.
código de muestra para ejecutar los comandos ingresados por el usuario
def execute_commands(command):
try:
subprocess.run(command.split())
except Exception:
print("psh: command not found: {}".format(command))