Python 异常在多线程中如何传播?
技术百科
舞姬之光
发布时间:2026-01-22
浏览: 次 Python异常默认不跨线程传播,因各线程有独立栈和异常上下文;子线程未捕获异常时仅触发threading.excepthook,默认打印traceback后退出,不会通知主线程。
Python 中的异常默认不会跨线程传播。主线程无法直接捕获子线程中发生的异常,子线程崩溃也不会中断主线程或其他线程。
为什么异常不自动传播?
每个线程有独立的执行栈和异常处理上下文。当子线程抛出未捕获异常时,Python 会调用 threading.excepthook(默认打印 traceback 并退出该线程),但不会向上通知创建它的线程。
手动捕获并传递异常的常用方法
需要显式将异常信息从子线程“带出来”,常见做法有:
-
使用
queue.Queue:子线程把异常对象(或 (type, value, traceback) 元组)放入队列,主线程定时检查并重新抛出 -
保存到共享变量 + 标志位:用
threading.Event或普通变量标记失败,并将sys.exc_info()结果存入线程安全容器(如threading.local()或加锁的 dict) -
使用
concurrent.futures.ThreadPoolExecutor:调用future.result()时,若子线程出错,会原样抛出该异常(推荐,封装了传播逻辑)
ThreadPoolExecutor 是最简洁的方案
它内部通过 _result 和 _exception 属性保存执行结果或异常,并在 result() 调用时触发重抛:
from concurrent.futures import ThreadPoolExecutor import timedef risky_task(): time.sleep(0.1) raise ValueError("子线程出错了")
with ThreadPoolExecutor() as executor: future = execu
tor.submit(risky_task) try: future.result() # 这里会抛出 ValueError except ValueError as e: print(f"捕获到:{e}") # 输出:捕获到:子线程出错了
自定义 excepthook 可用于日志或调试
如果不想让线程静默退出,可设置全局钩子:
import threading import sysdef custom_hook(args): print(f"[线程异常] {args.thread.name}: {args.exc_value}")
threading.excepthook = custom_hook
def bad_func(): raise RuntimeError("boom")
threading.Thread(target=bad_func).start() # 触发 custom_hook
注意:这仅用于记录,不能替代异常传播逻辑。
# ai
# python
# 但不
# 并在
# 想让
# 自定义
# 并将
# 或其他
# 装了
# 对象
# 为什么
# 线程
# 栈
# Event
# 多线程
# 封装
# 错了
# 抛出
# 主线程
# 会向
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win10怎样安装Word样式库_Win10安装W
- php订单日志怎么按状态筛选_php筛选不同状态订
- Python列表推导式与字典推导式教程_简化代码高
- php增删改查报错1054怎么办_字段名错误排查修
- Python邮件系统自动化教程_批量发送解析与模板
- 如何在Golang中实现文件下载_Golang文件
- Golang如何实现基本的用户注册_Golang用
- 如何用::实现工具类方法调用_php静态工具类设计
- Linux怎么查找死循环进程_Linux系统负载分
- c++的STL算法库find怎么用 在容器中查找指
- Linux如何申请SSL免费证书_Linux下Ce
- Win11怎么设置任务栏透明_Windows11使
- Mac怎么安装软件_Mac安装dmg与pkg文件的
- Linux如何安装Golang环境_Linux下G
- PHP主流架构如何处理会话管理_Session与C
- 如何在Golang中定义接口_抽象方法和多态实现
- php和redis连接超时怎么办_phpredis
- Python集合操作技巧_高效去重解析【教程】
- 如何在Mac上搭建Golang开发环境_使用Hom
- Windows10如何查看保存的WiFi密码_Wi
- C#如何使用Channel C#通道实现异步通信
- php条件判断怎么写_ifelse和switchc
- c++ stringstream用法详解_c++字
- Win11怎么关闭搜索历史 Win11清除搜索框最
- 电脑无法识别U盘怎么办 Windows磁盘管理与驱
- mac怎么安装adb_MAC配置Android A
- 如何使用Golang写入二进制文件_Golang
- Win10如何备份驱动程序_Win10驱动备份步骤
- Windows 11无法安全删除U盘提示设备正在使
- ACF 教程:如何正确更新嵌套在多层 Group
- Python配置文件操作教程_JSONINIYAM
- Win11怎样安装剪映专业版_Win11安装剪映教
- Windows蓝屏错误0x0000002C怎么解决
- 如何在Golang中编写端到端测试_Golang
- Win11怎么打开注册表_Windows 11注册
- Windows资源管理器总是卡顿或重启怎么办?(修
- php中::能访问全局变量吗_全局作用域与类作用域
- Win11怎么设置鼠标宏_Win11鼠标按键自定义
- Mac怎么设置登录项_Mac管理开机自启动程序【教
- Windows 10怎么录屏_Windows 10
- c++的static关键字有什么用 静态变量和静态
- php8.4如何调用com组件_php8.4win
- Mac如何使用听写功能_Mac语音输入打字【效率技
- 如何在 Go 项目开发中正确处理本地包导入与远程模
- LINUX如何查看文件类型_Linux中file命
- 如何使用Golang搭建Web开发环境_快速启动H
- Win11怎么关闭VBS安全性_Windows11
- Win11如何更改任务栏颜色 Win11自定义任务
- Python解释执行模型_字节码流程说明【指导】
- MAC怎么用连续互通相机里的“桌上视角”_MAC在


QQ客服