[python] try-except없이 Python에서 keyboardinterrupt 캡처

파이썬에서 KeyboardInterrupt모든 코드를 tryexcept문 안에 넣지 않고 이벤트 를 캡처하는 방법이 있습니까?

사용자가 Ctrl+를 누르면 흔적없이 깔끔하게 종료하고 싶습니다 C.



답변

예, 모듈 신호를 사용하여 인터럽트 핸들러를 설치 하고 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()


답변

트레이스 백을 표시하지 않으려면 다음과 같이 코드를 작성하십시오.

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

이것은 무슨 일이 일어나고 있는지에 대한 명시적인 언급을 유지하면서 tryexcept블록을 제거합니다 .

또한 매번 신호 처리기를 다시 설정하고 재설정 할 필요없이 코드의 일부 부분에서만 인터럽트를 무시할 수 있습니다.


답변

나는 이것이 오래된 질문이라는 것을 알고 있지만 먼저 여기에 와서 atexit모듈 을 발견했습니다 . 아직까지는 크로스 플랫폼 실적이나 전체주의 사항 목록에 대해 알지 못합니다.하지만 지금까지 KeyboardInterruptLinux에서 사후 정리 를 처리 할 때 찾던 것이 바로 그것입니다 . 문제에 접근하는 다른 방법을 던지고 싶었습니다.

Fabric 작업의 맥락에서 종료 후 정리를 수행하고 싶으므로 모든 것을 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-function이 예외에 대해 알 수있는 방법을 생각할 수 없습니다. atexit핸들러는 예외를 포착하고 콜백을 호출 한 다음 다시 발생합니다. 예외입니다.하지만 다르게 할 수 있습니다.)

자세한 내용은 다음을 참조하십시오.


답변

을 대체하여 (가장 분명하고 적절한 “최상의”솔루션이지만 이미 알고 있고 다른 것을 요청한 KeyboardInterrupt)없이에 대한 스택 추적 인쇄를 방지 할 수 있습니다 . 같은 것try: ... except KeyboardInterrupt: passsys.excepthook

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


답변

나는 모든 사람들이 제안한 해결책을 시도했지만 실제로 작동하도록 코드를 직접 수정해야했습니다. 다음은 즉석 코드입니다.

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


답변

누군가가 빠른 최소 솔루션을 찾고 있다면

import signal

# The code which crashes program on interruption

signal.signal(signal.SIGINT, call_this_function_if_interrupted)

# The code skipped if interrupted