Réponses:
Oui, vous pouvez installer un gestionnaire d'interruption à l'aide du signal du module et attendre indéfiniment à l'aide d'un thread .
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
, cependant. (Dans ce style, ce while True: pass
serait plus soigné, de toute façon.) Ce serait très inutile; essayez quelque chose comme while True: time.sleep(60 * 60 * 24)
(dormir un jour à la fois est un chiffre entièrement arbitraire).
time
(comme vous devriez), n'oubliez pas de import time
:)
Si tout ce que vous voulez est de ne pas afficher le traçage, créez votre code comme ceci:
## all your app logic here
def main():
## whatever your app does.
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
# do nothing here
pass
(Oui, je sais que cela ne répond pas directement à la question, mais il n'est pas vraiment clair pourquoi avoir besoin d'un bloc try / except est répréhensible - peut-être que cela le rend moins ennuyeux pour l'OP)
signal.signal( signal.SIGINT, lambda s, f : sys.exit(0))
fait toujours.
Une alternative à la configuration de votre propre gestionnaire de signal consiste à utiliser un gestionnaire de contexte pour intercepter l'exception et l'ignorer:
>>> 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
...
>>>
Cela supprime le bloc try
- except
tout en conservant une mention explicite de ce qui se passe.
Cela vous permet également d'ignorer l'interruption uniquement dans certaines parties de votre code sans avoir à définir et réinitialiser à nouveau les gestionnaires de signaux à chaque fois.
Je sais que c'est une vieille question mais je suis venu ici en premier et j'ai découvert le atexit
module. Je ne connais pas encore ses antécédents multiplateformes ou une liste complète de mises en garde, mais jusqu'à présent, c'est exactement ce que je recherchais en essayant de gérer le post- KeyboardInterrupt
nettoyage sous Linux. Je voulais juste proposer une autre manière d'aborder le problème.
Je veux faire un nettoyage post-sortie dans le contexte des opérations Fabric, donc emballer tout dans try
/ except
n'était pas non plus une option pour moi. Je pense que cela atexit
peut être un bon choix dans une telle situation, où votre code n'est pas au plus haut niveau du flux de contrôle.
atexit
est très capable et lisible hors de la boîte, par exemple:
import atexit
def goodbye():
print "You are now leaving the Python sector."
atexit.register(goodbye)
Vous pouvez également l'utiliser comme décorateur (à partir de 2.6; cet exemple est tiré de la documentation):
import atexit
@atexit.register
def goodbye():
print "You are now leaving the Python sector."
Si vous souhaitez le rendre spécifique KeyboardInterrupt
uniquement, la réponse d'une autre personne à cette question est probablement meilleure.
Mais notez que le atexit
module ne contient que ~ 70 lignes de code et qu'il ne serait pas difficile de créer une version similaire qui traite les exceptions différemment, par exemple en passant les exceptions comme arguments aux fonctions de rappel. (La limitation de atexit
cela justifierait une version modifiée: actuellement, je ne peux pas concevoir de moyen pour les fonctions de rappel de sortie de connaître les exceptions; le atexit
gestionnaire intercepte l'exception, appelle votre (vos) rappel (s), puis re-déclenche cette exception. Mais vous pouvez le faire différemment.)
Pour plus d'informations, voir:
atexit
Vous pouvez empêcher l'impression d'une trace de pile pour KeyboardInterrupt
, sans try: ... except KeyboardInterrupt: pass
(la solution la plus évidente et probablement la «meilleure», mais vous la connaissez déjà et avez demandé autre chose) en remplaçant sys.excepthook
. Quelque chose comme
def custom_excepthook(type, value, traceback):
if type is KeyboardInterrupt:
return # do nothing
else:
sys.__excepthook__(type, value, traceback)
J'ai essayé les solutions suggérées par tout le monde, mais j'ai dû improviser moi-même le code pour le faire fonctionner. Voici mon code improvisé:
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