本文目录导读:

Python asyncio 全局异常捕获
使用 loop.set_exception_handler()
import asyncio
import sys
import traceback
def global_exception_handler(loop, context):
"""
全局异常处理器
"""
# 获取异常信息
exception = context.get('exception')
message = context.get('message', '发生未知错误')
# 获取调用栈信息
if exception:
print(f"全局异常捕获: {type(exception).__name__}: {exception}")
traceback.print_exception(type(exception), exception, exception.__traceback__)
else:
print(f"错误信息: {message}")
# 获取出错的协程
future = context.get('future')
if future:
print(f"出错的协程: {future}")
# 可以记录到日志文件
with open('error.log', 'a') as f:
f.write(f"{message}\n")
if exception:
traceback.print_exception(type(exception), exception, exception.__traceback__, file=f)
async def risky_task(name):
"""可能抛出异常的任务"""
await asyncio.sleep(1)
if name == "task2":
raise ValueError(f"任务 {name} 出错!")
print(f"任务 {name} 完成")
return name
async def main():
# 获取事件循环并设置全局异常处理器
loop = asyncio.get_event_loop()
loop.set_exception_handler(global_exception_handler)
# 创建多个任务
tasks = [
asyncio.create_task(risky_task("task1")),
asyncio.create_task(risky_task("task2")),
asyncio.create_task(risky_task("task3")),
]
# 等待所有任务完成(包括出错的任务)
results = await asyncio.gather(*tasks, return_exceptions=True)
# 处理结果
for i, result in enumerate(results):
if isinstance(result, Exception):
print(f"任务 {i+1} 返回异常: {result}")
else:
print(f"任务 {i+1} 返回结果: {result}")
if __name__ == "__main__":
asyncio.run(main())
使用装饰器捕获单个协程异常
import asyncio
import functools
import traceback
def catch_coroutine_error(func):
"""
装饰器:捕获协程中的异常
"""
@functools.wraps(func)
async def wrapper(*args, **kwargs):
try:
return await func(*args, **kwargs)
except Exception as e:
print(f"协程 {func.__name__} 发生异常: {e}")
traceback.print_exc()
# 可以选择重新抛出、返回默认值或记录日志
return None # 返回默认值
return wrapper
@catch_coroutine_error
async def risky_operation(name):
"""可能出错的操作"""
await asyncio.sleep(1)
raise RuntimeError(f"{name} 操作失败")
return "成功"
async def main():
results = await asyncio.gather(
risky_operation("操作1"),
risky_operation("操作2"),
return_exceptions=False
)
print(f"结果: {results}")
asyncio.run(main())
完善的全局异常捕获框架
import asyncio
import logging
import traceback
import sys
from typing import Optional, Callable, Any
class GlobalExceptionHandler:
"""全局异常捕获管理器"""
def __init__(self):
self.setup_logging()
self.handlers = []
def setup_logging(self):
"""设置日志系统"""
logging.basicConfig(
level=logging.ERROR,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('async_errors.log'),
logging.StreamHandler(sys.stdout)
]
)
self.logger = logging.getLogger(__name__)
def add_handler(self, handler: Callable):
"""添加自定义异常处理器"""
self.handlers.append(handler)
def exception_handler(self, loop: asyncio.AbstractEventLoop, context: dict):
"""全局异常处理器"""
exception = context.get('exception')
message = context.get('message', '未捕获的异常')
# 记录日志
self.logger.error(f"全局异常: {message}")
if exception:
self.logger.error(f"异常类型: {type(exception).__name__}")
self.logger.error(f"异常信息: {str(exception)}")
self.logger.error(f"堆栈信息:\n{''.join(traceback.format_tb(exception.__traceback__))}")
# 调用自定义处理器
for handler in self.handlers:
try:
handler(loop, context)
except Exception as e:
self.logger.error(f"自定义处理器出错: {e}")
# 可以在这里决定是否终止程序
# loop.stop()
class SafeTask:
"""安全任务包装器"""
def __init__(self, coro, name: str = None, on_error: Optional[Callable] = None):
self.coro = coro
self.name = name or getattr(coro, '__name__', 'unknown')
self.on_error = on_error
async def run(self):
"""安全执行协程"""
try:
return await self.coro
except asyncio.CancelledError:
logging.warning(f"任务 {self.name} 被取消")
raise
except Exception as e:
error_info = {
'task_name': self.name,
'exception': e,
'traceback': traceback.format_exc()
}
# 记录错误
logging.error(f"任务 {self.name} 执行失败: {e}")
logging.error(f"完整错误信息:\n{traceback.format_exc()}")
# 调用自定义错误处理函数
if self.on_error:
await self.on_error(error_info)
# 可以选择重新抛出或返回默认值
return None
async def example_usage():
"""使用示例"""
# 创建全局异常处理器
error_handler = GlobalExceptionHandler()
# 添加自定义处理器
async def custom_handler(loop, context):
print(f"自定义处理: {context.get('message')}")
error_handler.add_handler(custom_handler)
# 设置事件循环的异常处理器
loop = asyncio.get_event_loop()
loop.set_exception_handler(error_handler.exception_handler)
# 使用安全包装器执行任务
async def risky_task():
raise ValueError("模拟错误")
safe_task = SafeTask(
risky_task(),
name="risky_task",
on_error=lambda info: print(f"任务错误回调: {info['exception']}")
)
result = await safe_task.run()
print(f"安全任务返回: {result}")
# 或者直接创建任务
task = asyncio.create_task(risky_task())
try:
await task
except Exception as e:
print(f"捕获到异常: {e}")
if __name__ == "__main__":
asyncio.run(example_usage())
使用 asyncio 的 await 和 Task 异常
import asyncio
import traceback
async def task_with_timeout():
"""带超时的任务"""
try:
await asyncio.sleep(2)
raise ValueError("任务超时异常")
except asyncio.TimeoutError:
print("任务超时")
return None
async def monitor_tasks(tasks):
"""监控任务执行情况"""
for task in tasks:
if task.done():
if not task.cancelled() and task.exception():
print(f"任务异常: {task.exception()}")
traceback.print_exception(
type(task.exception()),
task.exception(),
task.exception().__traceback__
)
async def main():
# 创建并启动任务
tasks = [
asyncio.create_task(task_with_timeout(), name=f"task_{i}")
for i in range(3)
]
# 定期检查任务状态
while not all(t.done() for t in tasks):
await asyncio.sleep(0.1)
monitor_tasks(tasks)
# 收集结果
for task in tasks:
try:
result = await task
print(f"任务 {task.get_name()} 完成: {result}")
except Exception as e:
print(f"任务 {task.get_name()} 异常: {e}")
asyncio.run(main())
使用建议
-
选择合适的方案:
- 全局处理器:统一处理所有未捕获异常
- 装饰器:精确控制单个协程
- 安全包装器:灵活的异常处理
-
日志记录:务必记录异常日志便于调试
-
异常恢复:考虑是否允许程序继续运行
-
资源清理:异常发生时确保释放资源
-
测试覆盖:确保异常处理逻辑经过充分测试
这些方案可以根据项目需求灵活组合使用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播