2011-03-29 59 views
10

Actualmente necesito proporcionar interrupciones de teclado múltiples para un programa. ¿Hay una manera fácil de hacer esto con la clase de señal? Actualmente uso el SIGINT/Ctrl+C pero no puedo encontrar ninguna otra asignación de teclado.Python: Señal de teclado/interrupciones incorporadas

Sería bueno tener más de 2 señales. ¿Cómo puedo definir más señales o hay una mejor manera de capturar una "interrupción de un usuario"?

Aquí es una vista de alto nivel del código actual:

def shutdown(signal, frame): 
     if(signal==2): #sigint 
      print 'do something' 
     elif signal==XX: 
      print 'do something else' 
     # continued... 

signal.signal(signal.SIGINT, shutdown) 
signal.signal(signal.SOMEOTHERTYPE, shutdown) 


print 'start' 
t = Thread(target=run) 
t.setDaemon(True) 
t.start() 

print 'Done, press ctrl c, or ctrl ? ' 
signal.pause() 
+0

'2' es siempre cierto. – delnan

+0

en qué plataforma? soporte de señal en Windows le faltan muchas señales ... –

+0

Está etiquetado, linux. – Nix

Respuesta

11

El Ctrl+\ que se ha mencionado es interpretado por el software de su terminal, y la vinculación de la clave se configura a través del stty. A menos que tenga alguna forma de personalizar el software de su terminal, solo podrá usar las pocas señales que ya están integradas.

Dependiendo de la cantidad de funcionalidad que necesite o de la distancia que desee tomar, otra opción es para escribir su propio "terminal de ejecución de proceso" simple. Esta sería una secuencia de comandos que ejecuta una aplicación para usted y coloca su terminal en modo raw para que pueda procesar las pulsaciones de teclas que realizan acciones personalizadas.

A continuación se muestra un ejemplo simplificado que muestra lo que quiero decir. También puede hacer algo similar a través de curses o urwid si lo desea.

Manejar salida del proceso que había necesidad de capturar el stdout/stderr de y mostrarlo adecuadamente a la pantalla, usando si está manipulando el terminal manualmente, o usando un widget de urwid para mostrar el resultado en una ventana de desplazamiento, etc. La misma idea también se extendería a otros sistemas GUI (wx, tkinter, etc.) pero se mencionó el control terminal.

Aquí es term.py que implementa un intérprete de terminal prima básica:

import os, signal, subprocess, sys, tty, termios 

sigmap = { 
    '\x15': signal.SIGUSR1,  # ctrl-u 
    '\x1c': signal.SIGQUIT,  # ctrl-\ 
    '\x08': signal.SIGHUP,  # ctrl-h 
    '\x09': signal.SIGINT,  # ctrl-i 
    } 
# setup tty 
fd = sys.stdin.fileno() 
old_tc = termios.tcgetattr(fd) 
tty.setraw(fd) 
# spawn command as a child proc 
cmd = sys.argv[1:] 
proc = subprocess.Popen(cmd) 
while 1: 
    try: 
     ch = sys.stdin.read(1) 
     # example of ansi escape to move cursor down and to column 0 
     print '\033[1Eyou entered', repr(ch) 
     if ch == 'q': 
      break 
     signum = sigmap.get(ch) 
     if signum: 
      os.kill(proc.pid, signum) 
    finally: 
     pass 
termios.tcsetattr(fd, termios.TCSANOW, old_tc) 
sys.exit() 

Aquí es un simple script target.py a girar e imprimir las señales que recibe: ejemplo

import signal, sys, time 

def handler(num, _): 
    print 'got:', sigmap.get(num, '<other>') 
    if num == signal.SIGINT: 
     sys.exit(1) 
    return 1 

signames = ['SIGINT','SIGHUP','SIGQUIT','SIGUSR1'] 
sigmap = dict((getattr(signal, k), k) for k in signames) 
for name in signames: 
    signal.signal(getattr(signal, name), handler) 
while 1: 
    time.sleep(1) 

Uso:

% python term.py python target.py 
you entered 'h' 
you entered 'i' 
you entered '\x1c' 
        got: SIGQUIT 
you entered '\x15' 
        got: SIGUSR1 
you entered '\x08' 
        got: SIGHUP 
you entered '\t' 
       got: SIGINT 
you entered 'q' 
5

En los sistemas Linux, Ctrl + \ generará una señal signal.SIGQUIT.

+1

¿Hay alguna manera de definir nuevos? ¿O más? – Nix

0

No estoy seguro de si existe una forma premezclada de definir nuevas señales y asignarlas a eventos de teclado.

Si necesita ese tipo de flexibilidad, es posible que deba utilizar un subproceso de interfaz que permanezca en primer plano y que esté atento a los eventos del teclado. Luego podría comunicarse con otros hilos de cualquier manera que desee.

Cuestiones relacionadas