在 Python 中,當用戶按下 Ctrl+C 時,程序默認會觸發 KeyboardInterrupt
異常并終止。
1. 捕獲 KeyboardInterrupt
異常(推薦)
使用 try-except
塊直接捕獲 KeyboardInterrupt
異常,適用于簡單場景。
示例代碼:
try:while True:print("程序運行中,按 Ctrl+C 終止...")
except KeyboardInterrupt:print("\n檢測到 Ctrl+C!執行清理操作后退出。")
- 特點:
- 代碼簡潔,適合快速實現中斷處理。
- 可與其他異常(如
Exception
)分開處理,避免混淆邏輯。
- 適用場景:單線程腳本、需要即時響應中斷的場景。
2. 使用 signal
模塊處理信號
通過監聽操作系統信號 SIGINT
(對應 Ctrl+C)實現全局中斷處理,適用于復雜場景(如資源清理或數據保存)。
示例代碼:
import signal
import sysdef signal_handler(sig, frame):print("\n捕獲到 Ctrl+C,正在保存數據...")sys.exit(0)signal.signal(signal.SIGINT, signal_handler) # 綁定信號處理器while True:print("程序運行中,按 Ctrl+C 終止...")
- 特點:
- 支持更靈活的信號處理(如同時處理
SIGTERM
)。 - 允許多線程環境中主線程統一管理中斷。
- 支持更靈活的信號處理(如同時處理
- 進階用法(封裝為類):
通過類封裝可保存中斷時的狀態(如最后處理的數據)。class DataProcessor:def __init__(self):self.data = []signal.signal(signal.SIGINT, self.handler)def handler(self, sig, frame):print(f"保存最后一條數據:{self.data[-1]}")sys.exit(0)def run(self):while True:self.data.append(len(self.data))
3. 全局異常鉤子(sys.excepthook
)
修改全局異常鉤子,統一處理所有未捕獲的異常(包括 KeyboardInterrupt
)。
示例代碼:
import sys
import timedef global_except_hook(exctype, value, traceback):if exctype == KeyboardInterrupt:print("\n全局捕獲 Ctrl+C,正在終止...")sys.exit(0)sys.__excepthook__(exctype, value, traceback) # 處理其他異常sys.excepthook = global_except_hookdef main():while True:print("程序運行中...")time.sleep(1)if __name__ == "__main__":main()
- 特點:適用于未顯式使用
try-except
的場景,如第三方庫代碼引發的中斷。
4. 多線程環境處理
在多線程中需注意信號處理的主線程綁定和線程間通信。
示例代碼:
import signal
import threadingdef worker():while True:print("工作線程運行中...")def signal_handler(sig, frame):print("\n主線程收到 Ctrl+C,通知工作線程停止...")# 此處可設置事件標志通知線程退出exit(0)signal.signal(signal.SIGINT, signal_handler)
thread = threading.Thread(target=worker)
thread.start()while True:pass
- 注意事項:
- 信號處理器需在主線程中注冊。
- 線程終止可通過事件標志(
threading.Event
)或隊列(queue.Queue
)實現協同。
5. 注意事項
- 避免忽略異常:直接
except:
會屏蔽所有異常,建議明確捕獲KeyboardInterrupt
。 - 資源釋放:在處理器中關閉文件、釋放鎖或回滾事務,防止數據損壞。
- 信號處理限制:部分信號(如
SIGKILL
)無法被捕獲。 - 異步任務處理:長時間運行的 C 擴展代碼可能延遲信號響應,需結合
faulthandler
模塊調試。
應用場景
場景 | 推薦方法 | 引用來源 |
---|---|---|
簡單腳本終止 | try-except | |
復雜資源清理 | signal 模塊 | |
全局未捕獲異常處理 | sys.excepthook | |
多線程/分布式程序 | 信號綁定 + 線程通信機制 |