Захват keyboardinterrupt в Python без try-except



есть ли способ в Python, чтобы захватить KeyboardInterrupt событие без размещения всего кода внутри try -except заявление?



Я хочу чисто выйти без следа, если пользователь нажимает Ctrl+C.

785   5  

5 ответов:

Да, вы можете установить обработчик прерываний с помощью модуля сигнал, и ждать вечно использованием нарезание резьбы.Событие:

import signal
import sys
import time

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()

Если все, что вы хотите, это не показывать трассировку, сделайте свой код следующим образом:

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


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

(Да, я знаю, что это не дает прямого ответа на вопрос, но не совсем понятно, почему необходимость в блоке try / except нежелательна - возможно, это делает его менее раздражающим для OP)

альтернативой настройке собственного обработчика сигналов является использование контекстного менеджера для перехвата исключения и его игнорирования:

>>> 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
... 
>>>

Это удаляет try -except блок при сохранении некоторого явного упоминания о том, что происходит.

Это также позволяет игнорировать прерывание только в некоторых частях вашего кода без необходимости устанавливать и снова сбрасывать обработчики сигналов каждый раз.

Я знаю, что это старый вопрос, но я пришел сюда первым, а затем обнаружил atexit модуль. Я еще не знаю о его кросс-платформенном послужном списке или полном списке предостережений, но до сих пор это именно то, что я искал, пытаясь справиться с post-KeyboardInterrupt очистка на Linux. Просто хотел бросить в другой способ подхода к проблеме.

Я хочу сделать очистку после выхода в контексте операций с тканью, поэтому обертывание всего в try/except не было вариант для меня. Я чувствую, что atexit может быть хорошо подходит в такой ситуации, когда ваш код не находится на верхнем уровне потока управления.

atexit очень способный и читаемый из коробки, например:

import atexit

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

atexit.register(goodbye)

вы также можете использовать его в качестве оформителя (в 2.6; этот пример из документации):

import atexit

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

если вы хотите сделать его специфичным для KeyboardInterrupt только, ответ другого человека на этот вопрос, вероятно, лучше.

но обратите внимание, что atexit модуль - это только ~70 строк кода, и было бы нетрудно создать аналогичную версию, которая обрабатывает исключения по-разному, например, передавая исключения в качестве аргументов функциям обратного вызова. (Ограничение atexit это гарантировало бы модифицированную версию: в настоящее время я не могу представить себе способ для функций exit-callback-знать об исключениях;atexit обработчик ловит исключение, вызывает ваш обратный вызов(ы), а затем повторно вызывает это исключение. Но вы могли бы сделать это по-другому.)

для получения дополнительной информации см.:

вы можете запретить печать трассировки стека для KeyboardInterrupt, без try: ... except KeyboardInterrupt: pass (наиболее очевидное и приемлемое "лучшее" решение, но вы уже знаете его и попросили что-то еще), заменив sys.excepthook. Что-то вроде

def custom_excepthook(type, value, traceback):
    if type is KeyboardInterrupt:
        return # do nothing
    else:
        sys.__excepthook__(type, value, traceback)

Comments

    Ничего не найдено.