KeyboardInterrupt触发时thread.join()报错问题求助
问题分析
你遇到的错误根源是:捕获KeyboardInterrupt后仅打印提示,未正确停止后台线程中的asyncio事件循环,导致thread.join()持续阻塞。此时若再次触发中断(比如重复按Ctrl+C),就会在join()调用时抛出异常。
解决方案
要实现优雅终止,需在捕获中断信号后先安全停止后台事件循环,再等待线程结束:
- 用
event_loop.call_soon_threadsafe(event_loop.stop)在主线程中通知后台事件循环停止(事件循环运行在其他线程,必须用线程安全的方式调用) - 若需要等待
foo任务完成后再退出,可额外添加任务取消或等待逻辑 - 最后调用
thread.join()等待线程正常退出
修正后的代码
import threading import asyncio import sys import time def callback_handler(name): print(f"Hi im a callback_handler, my name is {name}") async def foo(name, cb): await asyncio.sleep(5) print("Inside foo") if cb: await asyncio.sleep(5) # 同步回调建议放到线程池执行,避免阻塞事件循环 await asyncio.get_event_loop().run_in_executor(None, cb, name) event_loop = asyncio.new_event_loop() task = event_loop.create_task(foo("bar", callback_handler)) thread = threading.Thread(target=event_loop.run_forever, daemon=True) thread.start() try: while True: message = input("> ") except (KeyboardInterrupt, EOFError): print('Received KeyboardInterrupt') # 线程安全地停止事件循环 event_loop.call_soon_threadsafe(event_loop.stop) # 可选:若需要取消当前任务,可添加以下代码 # event_loop.call_soon_threadsafe(task.cancel) thread.join() print("Program exited gracefully")
额外说明
- 同步回调直接在async函数中调用会阻塞事件循环,用
run_in_executor放到线程池执行能避免影响其他异步任务 - 标记线程为
daemon=True后,主线程退出时守护线程会自动终止,但主动停止事件循环能实现更可控的优雅退出
内容的提问来源于stack exchange,提问作者Solo Bird
相关产品推荐
相关产品推荐

