2011-03-01 12 views
10

¿Por qué no Ctrl + C ¿funciona para romper un programa de Python que utiliza PyQt? Quiero depurarlo y obtener un seguimiento de pila y, por alguna razón, ¡esto es más difícil de hacer que con C++!Ctrl-C no funciona con PyQt

+0

¿Qué sistema operativo está utilizando? –

+4

Deberías haber usado Google ;-) [Tu problema se explicó con la solución] (http://www.mail-archive.com/[email protected]/msg13757.html) – user225312

+0

@A A - ¡Bien!Pensé que era una situación Ctrl + C versus Ctrl + D. –

Respuesta

19

CTRL + C hace que se envíe una señal al proceso . Python captura la señal y establece una variable global, algo así como CTRL_C_PRESSED = True. Luego, cada vez que el intérprete de Python llega a ejecutar un nuevo código de operación, ve la variable establecida y genera un KeybordInterrupt.

Esto significa que CTRL + C funciona solo si el intérprete de Python está girando. Si el intérprete está ejecutando un módulo de extensión escrito en C que ejecuta una operación de larga ejecución, CTRL + C no lo interrumpirá, a menos que explícitamente "coopere" con Python. Por ejemplo: time.sleep() es teóricamente una operación de bloqueo , pero la implementación de esa función "coopera" con el intérprete Python para hacer que CTRL + C funcione.

Esto es todo por diseño: CTRL + C significa para hacer un "aborto limpio"; esta es la razón por la cual se convierte en una excepción por Python (por lo que las limpiezas son ejecutadas durante el desenrollado de la pila), y su compatibilidad con por módulos de extensión es de "opt-in". Si desea totalmente abortar el proceso, sin darle una oportunidad de limpieza de , puede usar CTRL +.

Cuando Python llama QApplication :: exec() (la función C++), Qt no sabe cómo "cooperar" con Python para CTRL + C, y esto es por lo que no trabajo. No creo que haya una buena forma de de "hacer que funcione"; es posible que desee ver si puede manejarlo a través de un filtro de evento global . - Giovanni Bajo

Agregando esto al programa principal resuelto el problema.

import signal 

signal.signal(signal.SIGINT, signal.SIG_DFL) 

No estoy seguro de qué tiene esto que ver con la explicación.

+1

No tengo idea de lo que hace esto, pero funciona perfectamente. EDITAR: Lea un poco al respecto [aquí] (https://docs.python.org/3/library/signal.html) por lo que dice que SIGINT (= Ctrl + C) debería hacer la acción predeterminada (= salir) . – z3ntu

2

Estoy de acuerdo con Neil G, y añadiría esto:

Si lo hace, no QApplication.exec_ llamada() para iniciar el ciclo de eventos, y en lugar de ejecutar su programa en una cáscara de Python interactiva (usando Python -i), entonces pyqt procesará automáticamente los eventos cuando el indicador interactivo esté esperando, y Ctrl-C nuevamente debería comportarse como se esperaba. Esto se debe a que el ciclo de eventos de Qt compartirá el tiempo con el intérprete de Python, en lugar de ejecutarse exclusivamente, lo que permite al intérprete la oportunidad de detectar esas interrupciones.