是否有一些Python的方式捕捉KeyboardInterrupt
事件,而不把所有的代码try
内 - except
声明? 如果用户按下ctrl - c,我想干净地退出。捕捉Python中的一个KeyboardInterrupt没有尝试 - 除了
回答
是的,您可以使用signal module安装中断处理程序。
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'
while True:
time.sleep(1)
您可以防止打印堆栈跟踪KeyboardInterrupt
,没有try: ... except KeyboardInterrupt: pass
(最明显和最propably“最佳”的解决方案,但你已经知道了,问其他的东西),用sys.excepthook
。类似于
def custom_excepthook(type, value, traceback):
if type is KeyboardInterrupt:
return # do nothing
else:
sys.__excepthook__(type, value, traceback)
如果你想要的是不显示的回溯,使你的代码是这样的:
## all your app logic here
def main():
## whatever your app does.
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
# do nothing here
pass
(是的,我知道这并不直接回答这个问题,但它不是真的清楚为什么需要尝试/除了块是令人反感的 - 也许这使得它不那么烦人的OP)
出于某种原因,这并不总是适用于我。 'signal.signal(signal.SIGINT,lambda s,f:sys.exit(0))'总是这样。 – 2013-07-13 18:15:18
这并不总是适用于诸如使用线程的pygtk之类的东西。有时^ C只会杀死当前线程而不是整个进程,所以异常只会通过该线程传播。 – 2013-10-23 01:56:45
还有另外一个特别关于Ctrl + C与pygtk的问题:http://stackoverflow.com/questions/16410852/keyboard-interrupt-with-with-python-gtk – bgporter 2013-10-23 13:46:56
设置自己的信号处理程序的替代方法是使用上下文管理器来捕获异常并忽略它:
>>> 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
块,同时保留一些明确提及正在发生的事情。
这也允许您只在代码的某些部分忽略中断,而不必每次都设置和重新设置信号处理程序。
很好,这个解决方案确实似乎有点直接表达目的而不是处理信号。 – Seaux 2013-05-30 17:50:01
我知道这是一个老问题,但我先来到这里,然后发现atexit
模块。我不知道它的跨平台跟踪记录或完整的注意事项,但到目前为止,它正是我在试图处理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
这将保证修改版本:目前我无法想象退出回调函数知道异常的方法; atexit
处理程序捕获异常,调用您的回调,然后重新调用。-raises是例外,但你可以做不同的这个)
欲了解更多信息,请参阅:
- 1. 尝试除了没有捕捉异常
- 2. 尝试和捕捉laravel没有$ id
- 3. 尝试和除了没有循环 - Python
- 4. 主线程不捕捉KeyboardInterrupt
- 5. Python尝试除了未能捕获RemoteDataError
- 6. cakephp - 尝试/捕捉一个动作
- 7. $就尝试捕捉
- 8. Elixir尝试捕捉
- 9. 有没有办法尝试/动态捕捉整个页面?
- 10. 尝试捕捉性能c#
- 11. Powershell的尝试捕捉
- 12. 尝试不捕捉WebException
- 13. 尝试除了在Python中
- 14. 尝试抓住 - 不捕捉
- 15. 尝试,捕捉问题
- 16. 尝试捕捉细节
- 17. Python的硒尝试,除了
- 18. Java尝试/捕捉方法
- 19. 尝试捕捉问题
- 20. 尝试捕捉恢复
- 21. C++尝试捕捉做法
- 22. 尝试捕捉执行
- 23. 的jQuery没有试图捕捉的keyCode
- 24. 尝试和除了捕获所有错误,除了sys.exit()
- 25. 扭曲:捕捉一个KeyboardInterrupt和正常关机
- 26. 尝试捕捉list_to_integer不捕获错误
- 27. Python尝试除了最后
- 28. 尝试捕捉最后不捕捉异常
- 29. 我想尝试和捕捉双,但没有奏效
- 30. 错误的JavaScript尝试捕捉
请注意,有一些平台特定的问题与信号模块 - 不应该影响这张海报,但“在Windows上,信号()只能用SIGABRT,SIGFPE,SIGILL,SIGINT,SIGSEGV或SIGTERM来调用,任何其他情况下都会引发ValueError。 – bgporter 2010-11-17 14:39:11
也适用于线程。尽管如此,我希望你永远不要“真实:继续”。 (按照这种风格,无论如何,'虽然真实:通过'会更整洁。)那太浪费了;尝试类似'while True:time.sleep(60 * 60 * 24)'(一次睡一天完全是任意图)。 – 2011-10-06 12:04:30
如果你使用克里斯摩根的建议,使用'时间'(如你应该),不要忘了'进口时间':) – Seaux 2013-05-30 17:37:04