.. audit-event:: sys._current_exceptions "" sys._current_exceptions
+ .. versionchanged:: 3.12
+ Each value in the dictionary is now a single exception instance, rather
+ than a 3-tuple as returned from ``sys.exc_info()``.
+
.. function:: breakpointhook()
This hook function is called by built-in :func:`breakpoint`. By default,
:data:`sys.last_type`, :data:`sys.last_value` and :data:`sys.last_traceback`.
(Contributed by Irit Katriel in :gh:`102778`.)
+* :func:`sys._current_exceptions` now returns a mapping from thread-id to an
+ exception instance, rather than to a ``(typ, exc, tb)`` tuple.
+ (Contributed by Irit Katriel in :gh:`103176`.)
+
Optimizations
=============
synchronization is needed, implement locking within the cached property getter
function or around multi-threaded access points.
+* :func:`sys._current_exceptions` now returns a mapping from thread-id to an
+ exception instance, rather than to a ``(typ, exc, tb)`` tuple.
+ (Contributed by Irit Katriel in :gh:`103176`.)
+
Build Changes
=============
main_id = threading.get_ident()
self.assertIn(main_id, d)
self.assertIn(thread_id, d)
- self.assertEqual((None, None, None), d.pop(main_id))
+ self.assertEqual(None, d.pop(main_id))
# Verify that the captured thread frame is blocked in g456, called
# from f123. This is a little tricky, since various bits of
# threading.py are also in the thread's call stack.
- exc_type, exc_value, exc_tb = d.pop(thread_id)
- stack = traceback.extract_stack(exc_tb.tb_frame)
+ exc_value = d.pop(thread_id)
+ stack = traceback.extract_stack(exc_value.__traceback__.tb_frame)
for i, (filename, lineno, funcname, sourceline) in enumerate(stack):
if funcname == "f123":
break
--- /dev/null
+:func:`sys._current_exceptions` now returns a mapping from thread-id to an
+exception instance, rather than to a ``(typ, exc, tb)`` tuple.
if (id == NULL) {
goto fail;
}
- PyObject *exc_info = _PyErr_StackItemToExcInfoTuple(err_info);
- if (exc_info == NULL) {
- Py_DECREF(id);
- goto fail;
- }
- int stat = PyDict_SetItem(result, id, exc_info);
+ PyObject *exc = err_info->exc_value;
+ assert(exc == NULL ||
+ exc == Py_None ||
+ PyExceptionInstance_Check(exc));
+
+ int stat = PyDict_SetItem(result, id, exc == NULL ? Py_None : exc);
Py_DECREF(id);
- Py_DECREF(exc_info);
if (stat < 0) {
goto fail;
}