Antworten:
Ja, können Sie einen Interrupt - Handler mit dem Modul installieren Signal , und warten Sie für immer ein mit 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()
while True: continue
. (In diesem Stil while True: pass
wäre es sowieso ordentlicher.) Das wäre sehr verschwenderisch; Versuchen Sie etwas wie while True: time.sleep(60 * 60 * 24)
(einen Tag zu schlafen ist eine völlig willkürliche Zahl).
time
(wie Sie sollten), vergessen Sie nicht import time
:)
Wenn Sie den Traceback nur nicht anzeigen möchten, erstellen Sie Ihren Code folgendermaßen:
## all your app logic here
def main():
## whatever your app does.
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
# do nothing here
pass
(Ja, ich weiß, dass dies die Frage nicht direkt beantwortet, aber es ist nicht wirklich klar, warum die Notwendigkeit eines Try / Except-Blocks zu beanstanden ist - vielleicht macht es das OP weniger nervig)
signal.signal( signal.SIGINT, lambda s, f : sys.exit(0))
macht immer.
Eine Alternative zum Festlegen eines eigenen Signalhandlers besteht darin, einen Kontextmanager zu verwenden, um die Ausnahme abzufangen und zu ignorieren:
>>> 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
...
>>>
Dadurch wird der Block try
- entfernt except
, während explizit erwähnt wird, was gerade passiert.
Auf diese Weise können Sie den Interrupt auch nur in einigen Teilen Ihres Codes ignorieren, ohne die Signalhandler jedes Mal neu einstellen und zurücksetzen zu müssen.
Ich weiß, dass dies eine alte Frage ist, aber ich bin zuerst hierher gekommen und habe dann das atexit
Modul entdeckt. Ich weiß noch nichts über die plattformübergreifende Erfolgsbilanz oder eine vollständige Liste von Vorbehalten, aber bisher war es genau das, wonach ich gesucht habe, um die Nachbereinigung KeyboardInterrupt
unter Linux durchzuführen. Ich wollte nur eine andere Herangehensweise an das Problem einwerfen.
Ich möchte eine Bereinigung nach dem Beenden im Rahmen von Fabric-Vorgängen durchführen, daher war es für mich auch keine Option , alles in try
/ except
einzuwickeln. Ich denke, atexit
dass dies in einer solchen Situation gut passt, in der sich Ihr Code nicht auf der obersten Ebene des Kontrollflusses befindet.
atexit
ist sehr leistungsfähig und sofort lesbar, zum Beispiel:
import atexit
def goodbye():
print "You are now leaving the Python sector."
atexit.register(goodbye)
Sie können es auch als Dekorateur verwenden (ab 2.6; dieses Beispiel stammt aus den Dokumenten):
import atexit
@atexit.register
def goodbye():
print "You are now leaving the Python sector."
Wenn Sie es nur spezifisch machen möchten, KeyboardInterrupt
ist die Antwort einer anderen Person auf diese Frage wahrscheinlich besser.
Beachten Sie jedoch, dass das atexit
Modul nur ~ 70 Codezeilen umfasst und es nicht schwierig ist, eine ähnliche Version zu erstellen, die Ausnahmen unterschiedlich behandelt, z. B. die Ausnahmen als Argumente an die Rückruffunktionen zu übergeben. (Die Einschränkung atexit
würde eine modifizierte Version rechtfertigen: Derzeit kann ich mir keine Möglichkeit vorstellen, wie die Exit-Callback-Funktionen über die Ausnahmen Bescheid wissen können. Der atexit
Handler fängt die Ausnahme ab, ruft Ihre Rückrufe auf und löst sie dann erneut aus diese Ausnahme. Aber Sie könnten dies anders machen.)
Weitere Informationen finden Sie unter:
atexit
Sie können verhindern, dass eine Stapelverfolgung KeyboardInterrupt
ohne try: ... except KeyboardInterrupt: pass
(die offensichtlichste und wahrscheinlich "beste" Lösung, aber Sie kennen sie bereits und haben nach etwas anderem gefragt) gedruckt wird, indem Sie sie ersetzen sys.excepthook
. Etwas wie
def custom_excepthook(type, value, traceback):
if type is KeyboardInterrupt:
return # do nothing
else:
sys.__excepthook__(type, value, traceback)
Ich habe die vorgeschlagenen Lösungen von allen ausprobiert, aber ich musste den Code selbst improvisieren, damit er tatsächlich funktioniert. Folgendes ist mein improvisierter Code:
import signal
import sys
import time
def signal_handler(signal, frame):
print('You pressed Ctrl+C!')
print(signal) # Value is 2 for CTRL + C
print(frame) # Where your execution of program is at moment - the Line Number
sys.exit(0)
#Assign Handler Function
signal.signal(signal.SIGINT, signal_handler)
# Simple Time Loop of 5 Seconds
secondsCount = 5
print('Press Ctrl+C in next '+str(secondsCount))
timeLoopRun = True
while timeLoopRun:
time.sleep(1)
if secondsCount < 1:
timeLoopRun = False
print('Closing in '+ str(secondsCount)+ ' seconds')
secondsCount = secondsCount - 1