Domanda

C'è qualche modo in Python all'evento cattura KeyboardInterrupt senza mettere tutto il codice all'interno di un'istruzione try-except?

Voglio uscire in modo pulito senza lasciare traccia se l'utente preme Ctrl + C .

È stato utile?

Soluzione

Sì, è possibile installare un gestore di interrupt con il modulo segnale , e aspettare per sempre utilizzando un threading.Event :

import signal
import sys
import time
import threading

def signal_handler(signal, frame):
    print('You pressed Ctrl+C!')
    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C')
forever = threading.Event()
forever.wait()

Altri suggerimenti

Se invece si è di non mostrare il traceback, rendere il codice in questo modo:

## all your app logic here
def main():
   ## whatever your app does.


if __name__ == "__main__":
   try:
      main()
   except KeyboardInterrupt:
      # do nothing here
      pass

(Sì, lo so che questo non risponde direttamente alla domanda, ma in realtà non è chiaro il motivo che necessitano di un blocco try / except è discutibile - forse questo lo rende meno fastidioso per l'OP)

Un'alternativa a impostare il proprio gestore di segnale è quello di utilizzare un contesto-manager per catturare l'eccezione e ignorarlo:

>>> class CleanExit(object):
...     def __enter__(self):
...             return self
...     def __exit__(self, exc_type, exc_value, exc_tb):
...             if exc_type is KeyboardInterrupt:
...                     return True
...             return exc_type is None
... 
>>> with CleanExit():
...     input()    #just to test it
... 
>>>

Questo rimuove il blocco try-except pur conservando alcune menzione esplicita di ciò che sta accadendo.

Questo permette anche di ignorare l'interrupt solo in alcune parti del codice senza dover impostare e resettare nuovamente l'everytime gestori di segnale.

So che questa è una vecchia questione, ma sono venuto qui prima e poi scoperto il modulo atexit. Non so circa la sua esperienza cross-piattaforma o una lista completa di avvertimenti ancora, ma finora è esattamente quello che cercavo nel cercare di gestire post-KeyboardInterrupt pulizia su Linux. Volevo solo gettare in un altro modo di affrontare il problema.

voglio fare post-uscita clean-up nel contesto delle operazioni di tessuto, in modo da imballaggio tutto in try / except non era un'opzione per me. Mi sento come atexit può essere una buona forma in una situazione del genere, in cui il codice non è al livello superiore del flusso di controllo.

atexit è molto capace e fuori leggibile dalla scatola, per esempio:

import atexit

def goodbye():
    print "You are now leaving the Python sector."

atexit.register(goodbye)

Si può anche usarlo come decoratore (a partire da 2.6, questo esempio è dalla documentazione):

import atexit

@atexit.register
def goodbye():
    print "You are now leaving the Python sector."

Se si voleva renderlo specifico per KeyboardInterrupt solo, la risposta di un'altra persona a questa domanda è probabilmente meglio.

Ma si noti che il modulo atexit è solo ~ 70 linee di codice e non sarebbe difficile creare una versione simile che tratta le eccezioni in modo diverso, ad esempio passando le eccezioni come argomenti alle funzioni di callback. (La limitazione di atexit che giustifichino una versione modificata: attualmente non posso concepire un modo per l'uscita-callback funzioni di conoscere le eccezioni, il gestore atexit cattura l'eccezione, per chiamare la propria callback (s), poi ri -raises tale eccezione. Ma si potrebbe fare questo in modo diverso.)

Per maggiori informazioni visita:

È possibile evitare che la stampa di una traccia dello stack per KeyboardInterrupt senza try: ... except KeyboardInterrupt: pass (la soluzione più ovvia e riordinata "migliore", ma sai già che e ha chiesto per qualcos'altro) sostituendo sys.excepthook . Qualcosa di simile

def custom_excepthook(type, value, traceback):
    if type is KeyboardInterrupt:
        return # do nothing
    else:
        sys.__excepthook__(type, value, traceback)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top