[Python]獲取子線程異常信息


起因

今天在寫東西的時候,用到了多線程。遇到了個問題:

子線程的異常,在父線程中無法捕獲。

解決

問題代碼

問題代碼示例代碼如下:

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()

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM