@@ -3159,3 +3159,60 @@ def __enter__(self):
31593159 def __exit__ (self , * exc_info ):
31603160 sys .unraisablehook = self ._old_hook
31613161 del self .unraisable
3162+
3163+
3164+ class catch_threading_exception :
3165+ """
3166+ Context manager catching threading.Thread exception using
3167+ threading.excepthook.
3168+
3169+ Attributes set when an exception is catched:
3170+
3171+ * exc_type
3172+ * exc_value
3173+ * exc_traceback
3174+ * thread
3175+
3176+ See threading.excepthook() documentation for these attributes.
3177+
3178+ These attributes are deleted at the context manager exit.
3179+
3180+ Usage:
3181+
3182+ with support.catch_threading_exception() as cm:
3183+ # code spawning a thread which raises an exception
3184+ ...
3185+
3186+ # check the thread exception, use cm attributes:
3187+ # exc_type, exc_value, exc_traceback, thread
3188+ ...
3189+
3190+ # exc_type, exc_value, exc_traceback, thread attributes of cm no longer
3191+ # exists at this point
3192+ # (to avoid reference cycles)
3193+ """
3194+
3195+ def __init__ (self ):
3196+ self .exc_type = None
3197+ self .exc_value = None
3198+ self .exc_traceback = None
3199+ self .thread = None
3200+ self ._old_hook = None
3201+
3202+ def _hook (self , args ):
3203+ self .exc_type = args .exc_type
3204+ self .exc_value = args .exc_value
3205+ self .exc_traceback = args .exc_traceback
3206+ self .thread = args .thread
3207+
3208+ def __enter__ (self ):
3209+ self ._old_hook = threading .excepthook
3210+ threading .excepthook = self ._hook
3211+ return self
3212+
3213+ def __exit__ (self , * exc_info ):
3214+ threading .excepthook = self ._old_hook
3215+ del self .exc_type
3216+ del self .exc_value
3217+ del self .exc_traceback
3218+ del self .thread
0 commit comments