Toetsenbordinterrupt vangen in Python tijdens afsluiten van programma

Ik schrijf een commandoregelprogramma in Python dat, aangezien het productiecode is, in staat zou moeten zijn om netjes af te sluiten zonder een heleboel dingen (foutcodes, stapelsporen, enz.) op het scherm te dumpen. Dit betekent dat ik toetsenbordonderbrekingen moet opvangen.

Ik heb geprobeerd beide een try-catch-blok te gebruiken, zoals:

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print 'Interrupted'
        sys.exit(0)

en het signaal zelf opvangen (zoals in dit bericht):

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

Beide methoden lijken redelijk goed te werken tijdens normaal gebruik. Als de onderbreking echter komt tijdens het opschonen van code aan het einde van de toepassing, lijkt Python altijd iets op het scherm af te drukken. Het vangen van de interrupt geeft

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

terwijl het verwerken van het signaal een van beide geeft

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

of

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

Deze fouten zijn niet alleen lelijk, ze zijn ook niet erg nuttig (vooral voor een eindgebruiker zonder broncode)!

De opschooncode voor deze applicatie is vrij groot, dus er is een behoorlijke kans dat dit probleem door echte gebruikers wordt aangepakt. Is er een manier om deze uitvoer te onderscheppen of te blokkeren, of is het gewoon iets waar ik mee te maken krijg?


Antwoord 1, autoriteit 100%

Bekijk deze thread, deze bevat nuttige informatie over het afsluiten en tracebacks.

Als je er meer in geïnteresseerd bent om het programma gewoon te beëindigen, probeer dan iets als dit (dit haalt ook de benen onder de opruimcode vandaan):

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print('Interrupted')
        try:
            sys.exit(0)
        except SystemExit:
            os._exit(0)

Antwoord 2, autoriteit 7%

U kunt SIGINT’s negeren nadat het afsluiten is begonnen door signal.signal(signal.SIGINT, signal.SIG_IGN)te bellen voordat u uw opschooncode start.

Other episodes