是否有一些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 2.7:子線程不捕捉KeyboardInterrupt
- 4. 嘗試捕捉
- 5. 嘗試捕捉
- 6. 嘗試捕捉鉻沒有捕捉語法錯誤
- 7. Python沒有捕獲嘗試/除了錯誤
- 8. 嘗試和除了沒有循環 - Python
- 9. 主線程不捕捉KeyboardInterrupt
- 10. Python嘗試除了未能捕獲RemoteDataError
- 11. 與嘗試捕捉
- 12. cakephp - 嘗試/捕捉一個動作
- 13. $就嘗試捕捉
- 14. Elixir嘗試捕捉
- 15. 嘗試捕捉塊不捕捉?
- 16. 有沒有辦法嘗試捕捉整個控制器?
- 17. 有沒有辦法嘗試/動態捕捉整個頁面?
- 18. 不能在嘗試捕捉
- 19. 只需一個嘗試/除了lambda - Python?
- 20. 嘗試捕捉性能c#
- 21. Powershell的嘗試捕捉
- 22. 嘗試除了在Python中
- 23. 嘗試不捕捉WebException
- 24. 包裝現有的與嘗試捕捉
- 25. 嘗試抓住 - 不捕捉
- 26. 嘗試除了沒有捕獲類的IOError
- 27. 嘗試捕捉異常?
- 28. 嘗試,捕捉問題
- 29. 嘗試捕捉細節
- 30. Python的硒嘗試,除了
請注意,有一些平臺特定的問題與信號模塊 - 不應該影響這張海報,但「在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