파이썬에서 KeyboardInterrupt
모든 코드를 try
– except
문 안에 넣지 않고 이벤트 를 캡처하는 방법이 있습니까?
사용자가 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
...
>>>
이것은 무슨 일이 일어나고 있는지에 대한 명시적인 언급을 유지하면서 try
– except
블록을 제거합니다 .
또한 매번 신호 처리기를 다시 설정하고 재설정 할 필요없이 코드의 일부 부분에서만 인터럽트를 무시할 수 있습니다.
답변
나는 이것이 오래된 질문이라는 것을 알고 있지만 먼저 여기에 와서 atexit
모듈 을 발견했습니다 . 아직까지는 크로스 플랫폼 실적이나 전체주의 사항 목록에 대해 알지 못합니다.하지만 지금까지 KeyboardInterrupt
Linux에서 사후 정리 를 처리 할 때 찾던 것이 바로 그것입니다 . 문제에 접근하는 다른 방법을 던지고 싶었습니다.
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
핸들러는 예외를 포착하고 콜백을 호출 한 다음 다시 발생합니다. 예외입니다.하지만 다르게 할 수 있습니다.)
자세한 내용은 다음을 참조하십시오.
- 에 대한 공식 문서
atexit
- 금주 의 Python 모듈 게시물 , 좋은 소개
답변
을 대체하여 (가장 분명하고 적절한 “최상의”솔루션이지만 이미 알고 있고 다른 것을 요청한 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)
답변
나는 모든 사람들이 제안한 해결책을 시도했지만 실제로 작동하도록 코드를 직접 수정해야했습니다. 다음은 즉석 코드입니다.
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