起因

今天在写东西的时候,用到了多线程。遇到了个问题:

子线程的异常,在父线程中无法捕获。

解决

问题代码

问题代码示例代码如下:

import threading

class SampleThread(threading.Thread):
def run(self):
raise Exception('An error occured here.') def main():
try:
thread_obj = SampleThread()
thread_obj.start()
except Exception:
print 'catch that' if __name__ == '__main__':
main()

运行输出结果如下:

Exception in thread Thread-1:
Traceback (most recent call last):
File "/path/threading.py", line 810, in __bootstrap_inner
self.run()
File "/PycharmProjects/example/threading_example.py", line 15, in run
raise Exception('An error occured here.')
Exception: An error occured here.

解决办法

通过查看资料:http://stackoverflow.com/questions/2829329/catch-a-threads-exception-in-the-caller-thread-in-python

出现上述问题是因为:执行到 thread_obj.start() 时,父线程就会立即返回结果。然后,生成的子线程在自己独立的上下文中执行,并使用自己的堆栈。子线程发生的任何异常都是在子线程的上下文中,并且它在它自己的堆栈中(独立于父线程)。

所以,解决办法是:将这些信息传递给父线程。代码如下:

import sys
import threading
import Queue class ExcThread(threading.Thread): def __init__(self, bucket):
threading.Thread.__init__(self)
self.bucket = bucket def run(self):
try:
raise Exception('An error occured here.')
except Exception:
self.bucket.put(sys.exc_info()) def main():
bucket = Queue.Queue()
thread_obj = ExcThread(bucket)
thread_obj.start() while True:
try:
exc = bucket.get(block=False)
except Queue.Empty:
pass
else:
exc_type, exc_obj, exc_trace = exc
# deal with the exception
print exc_type, exc_obj
print exc_trace thread_obj.join(0.1)
if thread_obj.isAlive():
continue
else:
break if __name__ == '__main__':
import sys
import threading
import Queue class ExcThread(threading.Thread):
def __init__(self, bucket):
super(ExcThread, self).__init__()
self.bucket = bucket def run(self):
try:
raise Exception('An error occured here.')
except Exception:
# 异常信息元祖放入队列传递给父进程
self.bucket.put(sys.exc_info()) def main():
bucket = Queue.Queue()
thread_obj = ExcThread(bucket)
thread_obj.start() # 循环获取子线程的异常信息
while 1:
try:
exc = bucket.get(block=False)
except Queue.Empty:
pass
else:
exc_type, exc_obj, exc_trace = exc
# deal with the exception
print exc_type, exc_obj
print exc_trace # 防止阻塞
thread_obj.join(0.1)
if thread_obj.isAlive():
continue
else:
break if __name__ == '__main__':
main()

参考

[Python]获取子线程异常信息的更多相关文章

  1. python使用traceback获取详细的异常信息

    原创来自:https://blog.csdn.net/mengtao0609/article/details/55049059 python使用traceback获取详细的异常信息 2017年02月1 ...

  2. Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动线程

    Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动线程 一.捕获异常并重新启用线程 public class Testun { public static voi ...

  3. ARTS-S 获取子线程返回值注意事项

    #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h& ...

  4. python获取系统内存占用信息的实例方法

    psutil是一个跨平台库(http://code.google.com/p/psutil/),能够轻松实现获取系统运行的进程和系统利用率(包括CPU.内存.磁盘.网络等)信息.它主要应用于系统监控, ...

  5. python主线程捕获子线程异常

    python内置threading.Thread类创建的子线程抛出的异常无法在主线程捕获,可以对该类进行优化,为子线程添加exit code属性,主线程通过获取子线程的返回状态,来判断子线程中是否发生 ...

  6. python多线程获取子线程任务返回值

    今天想实现多线程更新资产信息,所以使用到了threading,但是我需要每个线程的返回值,这就需要我在threading.Thread的基础上进行封装 def auto_asset(node): re ...

  7. 黄聪:WordPress 多站点建站教程(四):获取子站点相关信息(站点的注册时间,修改时间,总文章数,URL等)

    1.获取子站点blogs表里面的内容信息 $blog_details = get_blog_details(1); echo 'Blog '.$blog_details->blog_id.' i ...

  8. Android利用Handler异步获取子线程中的产生的值

        本文首发于cartoon的博客     转载请注明出处:https://cartoonyu.github.io/cartoon-blog     近段时间有一个需求:在线获取图片并且显示在界面 ...

  9. python 获取淘宝商品信息

    python cookie 获取淘宝商品信息 # //get_goods_from_taobao import requests import re import xlsxwriter cok='' ...

随机推荐

  1. 从头开始搭建一个Spring boot+RabbitMQ环境

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  2. php上线教程----阿里云下设值二级域名并将项目上线

    在工作中,我们需要在一个主机地址下分配多个域名来上线多个项目,但是怎么设置一个二级域名并且完成上线项目的,接下来我们就以阿里云为例演示整个上线流程 首先登陆你的阿里云,找到你的域名 点击解析,进入解析 ...

  3. lazy ideas in programming

    lazy形容词,懒惰的,毫无疑问是一个贬义词.但是,对于计算机领域,lazy却是非常重要的优化思想:把任务推迟到必须的时刻,好处是避免重复计算,甚至不计算.本文的目的是抛砖引玉,总结一些编程中的laz ...

  4. 获取div滚动条的宽度

    获取滚动条的宽度: function getScrollWidth() { var noScroll, scroll, oDiv = document.createElement('div'); oD ...

  5. mysql远程连接权限

    环境:mysql6.0 .Navicat Premium 用户名:root 密码:123456  本地连接无问题 远程连接mysql的时候应该碰到Navicat Premium 报错. 错误代码是11 ...

  6. linux下载时提示请尝试移除磁盘中不需要的文件并重试,或者保存到其他位置

    因为我是用虚拟机装的linux,所以当时就分配了20G硬盘,下载了几个应用后再下载就提示我这个了.一开始我还以为是因为下载链接的问题,后来才知道原来是因为/tmp的满了. 然后我输入以下连个命令就能正 ...

  7. groovy学习(五) 命令行输入输出

    isr = new InputStreamReader(System.in);br = new BufferedReader(isr);name = br.readLine();println(&qu ...

  8. Gulp实现css、js、图片的压缩以及css、js文件的MD5命名

    目前做代码压缩合并的工具有很多,诸如gulp,webpack,grunt等等,可以说这些项目构建工具的功能非常之强大:图片压缩.图片转base64.css和js的压缩以及合并,文件的md5重命名 -- ...

  9. MySQL账户管理

    body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10 ...

  10. p1154 地平线

    题目描述 Farmer John的牛们认为,太阳升起的那一刻是一天中最美好的,在那时她们可以看到远方城市模糊的轮廓.显然,这些轮廓其实是城市里建筑物模糊的影子. 建筑物的影子实在太模糊了,牛们只好把它 ...