asyncio.gather(return_exceptions=True)返回混合结果列表,元素为正常值或Exception实例,需用isinstance(item, Exception)逐项判断;成功结果与异常可分别用列表推导式提取,并注意异常序列化、日志及内存问题。

调用 asyncio.gather(return_exceptions=True) 后,返回值是一个 list,其中每个元素要么是对应协程的正常返回值,要么是一个 Exception 实例(不是被抛出,而是作为值存在)。这意味着你不能直接对整个结果做逻辑判断或解包,必须逐项检查类型。
result[0].some_method(),结果在第 0 项是 TimeoutError 时直接报 AttributeError
isinstance(item, Exception) 判断,而不是靠 try/except 包裹访问BaseException 子类(如 SystemExit, KeyboardInterrupt)也可能出现,但通常 return_exceptions=True 只捕获协程内抛出的异常,不包括事件循环中断最常用模式是用列表推导式分离成功值和异常,同时保留原始索引关系便于调试。不要用 filter 或 map 隐藏类型判断逻辑,可读性差且难调试。
[r for r in results if not isinstance(r, Exception)] —— 只取成功结果[(i, r) for i, r in enumerate(results) if isinstance(r, Exception)] —— 带索引的异常列表,方便定位哪个任务失败isinstance(r, TimeoutError) 或 type(r).__name__,避免用 str(r) 做模糊匹配len(results) == len(expected_tasks),防止任务数传错导致漏判设为 False(默认)时,只要任一协程抛异常,gather 立即中止并把第一个异常原样抛出,其余协程可能还在运行(取决于是否已取消)。而 True 下所有协程都会完成,异常被“吞”进结果里——这是两种完全不同的错误处理契约。
True 的典型场景:批量请求 API,允许部分失败,后续要聚合统计或重试False 的典型场景:多个强依赖步骤(如先 auth 再 fetch),一个失败整条链无意义True 会多一次结果遍历判断,对几千个任务才需留意把整个 results 直接传给 logging.error(results) 或 json.dumps(results) 会失败——Exception 实例不可 JSON 序列化,logging 默认只打 repr,但可读性差。
str(e) 或 traceback.format_exception(type(e), e, e.__traceback__)
[r if not isinstance(r, Exception) else {'error': type(r).__name__, 'message': str(r)} for r in results]
__traceback__ 属性——它指向协程内出错位置,但仅在异常被 raise 过才有效;return_exceptions=True 下该属性仍保留,可用 traceback.print_exception() 打印完整上下文