SoFunction
Updated on 2024-11-16

python main thread captures child threads

Recently, while working on a project, I encountered a problem where the main thread was unable to catch an exception thrown in a child thread.

Let's start with the definition of a thread class

''''' 
Created on Oct 27, 2015 
 
@author: wujz 
''' 
import threading 
 
class runScriptThread(): 
 def __init__(self, funcName, *args): 
  .__init__(self) 
   = args 
   = funcName 
  
 def run(self): 
  try: 
   (*()) 
  except Exception as e: 
   raise e 

It's simple, pass in the method to be called and enable a new thread to run the method.

In the main thread, start an object of this thread class, it is necessary to declare an object and then start on it, the example is as follows

import runScriptThread,traceback 
 
if __name__=='__main__': 
 sth = 'hello world' 
 try: 
  aChildThread = runScriptThread(printSth, sth) 
  () 
  () 
 except Exception as e: 
  print(str(traceback.format_exc())) 

But with such code, the main method can't catch the exception in the subthread because the start() method will open a new stack for the subthread, and the main method's stack therefore can't catch the exception.

The solution is very simple, that is, by setting a member variable of whether the thread exits abnormally or not flag, when the thread exits abnormally, make a flag on it. Then in the main thread to check the value of the flag bit after the end of the thread, if the exception, and then through the sys and traceback back to the exception information, and then thrown can be. The rewritten exception class:

''''' 
Created on Oct 27, 2015 
 
@author: wujz 
''' 
import threading,traceback,sys 
 
class runScriptThread(): #The timer class is derived from the class  
 def __init__(self, funcName, *args): 
  .__init__(self) 
   = args 
   = funcName 
   = 0 
   = None 
  self.exc_traceback = '' 
  
 def run(self): #Overwrite run() method, put what you want the thread do here 
  try: 
   self._run() 
  except Exception as e: 
    = 1  # Set this flag bit to 1 if the thread exits abnormally, 0 for normal exit
    = e 
   self.exc_traceback = ''.join(traceback.format_exception(*sys.exc_info())) # Logging exceptions in changed member variables
  
 def _run(self): 
  try: 
   (*()) 
  except Exception as e: 
   raise e 

Rewritten main thread:

import runScriptThread,traceback 
 
if __name__=='__main__': 
 sth = 'hello world' 
 try: 
  aChildThread = runScriptThread(printSth, sth) 
  () 
  () 
 except Exception as e: 
  print(aChildThread.exc_traceback) 

All of the above is the entire content of this post.