Capturar o interrupto Keyboard em Python durante o encerramento do programa

estou a escrever um utilitário de linha de comando em Python que, uma vez que é um código de produção, deve ser capaz de desligar limpo sem despejar um monte de coisas (códigos de erro, pilhas de traços, etc.) para a tela. Isto significa que tenho de apanhar interrupções no teclado.

Já tentei usar um bloco de pesca como:
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print 'Interrupted'
        sys.exit(0)

e captando o próprio sinal (como em Este post):

import signal
import sys

def sigint_handler(signal, frame):
    print 'Interrupted'
    sys.exit(0)
signal.signal(signal.SIGINT, sigint_handler)

ambos os métodos parecem funcionar muito bem durante o funcionamento normal. No entanto, se a interromper vem durante o código de limpeza no final da aplicação, Python parece sempre imprimir algo para a tela. Apanhar a interrupção dá

^CInterrupted
Exception KeyboardInterrupt in <bound method MyClass.__del__ of <path.to.MyClass object at 0x802852b90>> ignored

considerando que a manipulação do sinal dá

^CInterrupted
Exception SystemExit: 0 in <Finalize object, dead> ignored

ou

^CInterrupted
Exception SystemExit: 0 in <bound method MyClass.__del__ of <path.to.MyClass object at 0x802854a90>> ignored

não só estes erros são feios, eles não são muito úteis (especialmente para um usuário final sem código fonte)!

o código de limpeza para esta aplicação é bastante grande, então há uma chance decente de que este problema será atingido por usuários reais. Existir há alguma forma de apanhar ou bloquear esta saída, ou é apenas algo com que terei de lidar?

Author: Community, 2014-01-14

2 answers

Checkout Este tópico, tem algumas informações úteis sobre a saída e tracebacks.

Se você está mais interessado em apenas matar o programa, Tente algo assim (isto irá tirar as pernas de dentro do código de limpeza também):

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print('Interrupted')
        try:
            sys.exit(0)
        except SystemExit:
            os._exit(0)
 62
Author: Dan Hogan, 2018-07-24 12:12:47

Podias ignorar SIGINTs após o encerramento começar por ligar para {[[0]} antes de iniciares o teu código de limpeza.

 5
Author: Dan Getz, 2014-01-15 15:38:19