mirror of https://github.com/python/cpython
bpo-46328: Add sys.exception() (GH-30514)
This commit is contained in:
parent
9c2ebb906d
commit
c590b581bb
|
@ -378,26 +378,41 @@ always available.
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.8
|
||||||
__unraisablehook__
|
__unraisablehook__
|
||||||
|
|
||||||
.. function:: exc_info()
|
|
||||||
|
|
||||||
This function returns a tuple of three values that give information about the
|
.. function:: exception()
|
||||||
exception that is currently being handled. The information returned is specific
|
|
||||||
both to the current thread and to the current stack frame. If the current stack
|
This function returns the exception instance that is currently being
|
||||||
frame is not handling an exception, the information is taken from the calling
|
handled. This exception is specific both to the current thread and
|
||||||
stack frame, or its caller, and so on until a stack frame is found that is
|
to the current stack frame. If the current stack frame is not handling
|
||||||
handling an exception. Here, "handling an exception" is defined as "executing
|
an exception, the exception is taken from the calling stack frame, or its
|
||||||
an except clause." For any stack frame, only information about the exception
|
caller, and so on until a stack frame is found that is handling an
|
||||||
being currently handled is accessible.
|
exception. Here, "handling an exception" is defined as "executing an
|
||||||
|
except clause." For any stack frame, only the exception being currently
|
||||||
|
handled is accessible.
|
||||||
|
|
||||||
.. index:: object: traceback
|
.. index:: object: traceback
|
||||||
|
|
||||||
If no exception is being handled anywhere on the stack, a tuple containing
|
If no exception is being handled anywhere on the stack, ``None`` is
|
||||||
three ``None`` values is returned. Otherwise, the values returned are
|
returned.
|
||||||
``(type, value, traceback)``. Their meaning is: *type* gets the type of the
|
|
||||||
exception being handled (a subclass of :exc:`BaseException`); *value* gets
|
.. versionadded:: 3.11
|
||||||
the exception instance (an instance of the exception type); *traceback* gets
|
|
||||||
a :ref:`traceback object <traceback-objects>` which typically encapsulates
|
|
||||||
the call stack at the point where the exception last occurred.
|
.. function:: exc_info()
|
||||||
|
|
||||||
|
This function returns the old-style representation of the handled
|
||||||
|
exception. If an exception ``e`` is currently handled (so
|
||||||
|
:func:`exception` would return ``e``), :func:`exc_info` returns the
|
||||||
|
tuple ``(type(e), e, e.__traceback__)``.
|
||||||
|
That is, a tuple containing the type of the exception (a subclass of
|
||||||
|
:exc:`BaseException`), the exception itself, and a :ref:`traceback
|
||||||
|
object <traceback-objects>` which typically encapsulates the call
|
||||||
|
stack at the point where the exception last occurred.
|
||||||
|
|
||||||
|
.. index:: object: traceback
|
||||||
|
|
||||||
|
If no exception is being handled anywhere on the stack, this function
|
||||||
|
return a tuple containing three ``None`` values.
|
||||||
|
|
||||||
.. versionchanged:: 3.11
|
.. versionchanged:: 3.11
|
||||||
The ``type`` and ``traceback`` fields are now derived from the ``value``
|
The ``type`` and ``traceback`` fields are now derived from the ``value``
|
||||||
|
|
|
@ -167,7 +167,7 @@ then re-raise the exception (allowing a caller to handle the exception as well):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
Alternatively the last except clause may omit the exception name(s), however the exception
|
Alternatively the last except clause may omit the exception name(s), however the exception
|
||||||
value must then be retrieved from ``sys.exc_info()[1]``.
|
value must then be retrieved with ``sys.exception()``.
|
||||||
|
|
||||||
The :keyword:`try` ... :keyword:`except` statement has an optional *else
|
The :keyword:`try` ... :keyword:`except` statement has an optional *else
|
||||||
clause*, which, when present, must follow all *except clauses*. It is useful
|
clause*, which, when present, must follow all *except clauses*. It is useful
|
||||||
|
|
|
@ -305,6 +305,9 @@ sys
|
||||||
the results of subsequent calls to :func:`exc_info`.
|
the results of subsequent calls to :func:`exc_info`.
|
||||||
(Contributed by Irit Katriel in :issue:`45711`.)
|
(Contributed by Irit Katriel in :issue:`45711`.)
|
||||||
|
|
||||||
|
* Add :func:`sys.exception` which returns the active exception instance
|
||||||
|
(equivalent to ``sys.exc_info()[1]``).
|
||||||
|
(Contributed by Irit Katriel in :issue:`46328`.)
|
||||||
|
|
||||||
threading
|
threading
|
||||||
---------
|
---------
|
||||||
|
|
|
@ -71,6 +71,69 @@ class DisplayHookTest(unittest.TestCase):
|
||||||
code = compile("42", "<string>", "single")
|
code = compile("42", "<string>", "single")
|
||||||
self.assertRaises(ValueError, eval, code)
|
self.assertRaises(ValueError, eval, code)
|
||||||
|
|
||||||
|
class ActiveExceptionTests(unittest.TestCase):
|
||||||
|
def test_exc_info_no_exception(self):
|
||||||
|
self.assertEqual(sys.exc_info(), (None, None, None))
|
||||||
|
|
||||||
|
def test_sys_exception_no_exception(self):
|
||||||
|
self.assertEqual(sys.exception(), None)
|
||||||
|
|
||||||
|
def test_exc_info_with_exception_instance(self):
|
||||||
|
def f():
|
||||||
|
raise ValueError(42)
|
||||||
|
|
||||||
|
try:
|
||||||
|
f()
|
||||||
|
except Exception as e_:
|
||||||
|
e = e_
|
||||||
|
exc_info = sys.exc_info()
|
||||||
|
|
||||||
|
self.assertIsInstance(e, ValueError)
|
||||||
|
self.assertIs(exc_info[0], ValueError)
|
||||||
|
self.assertIs(exc_info[1], e)
|
||||||
|
self.assertIs(exc_info[2], e.__traceback__)
|
||||||
|
|
||||||
|
def test_exc_info_with_exception_type(self):
|
||||||
|
def f():
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
try:
|
||||||
|
f()
|
||||||
|
except Exception as e_:
|
||||||
|
e = e_
|
||||||
|
exc_info = sys.exc_info()
|
||||||
|
|
||||||
|
self.assertIsInstance(e, ValueError)
|
||||||
|
self.assertIs(exc_info[0], ValueError)
|
||||||
|
self.assertIs(exc_info[1], e)
|
||||||
|
self.assertIs(exc_info[2], e.__traceback__)
|
||||||
|
|
||||||
|
def test_sys_exception_with_exception_instance(self):
|
||||||
|
def f():
|
||||||
|
raise ValueError(42)
|
||||||
|
|
||||||
|
try:
|
||||||
|
f()
|
||||||
|
except Exception as e_:
|
||||||
|
e = e_
|
||||||
|
exc = sys.exception()
|
||||||
|
|
||||||
|
self.assertIsInstance(e, ValueError)
|
||||||
|
self.assertIs(exc, e)
|
||||||
|
|
||||||
|
def test_sys_exception_with_exception_type(self):
|
||||||
|
def f():
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
try:
|
||||||
|
f()
|
||||||
|
except Exception as e_:
|
||||||
|
e = e_
|
||||||
|
exc = sys.exception()
|
||||||
|
|
||||||
|
self.assertIsInstance(e, ValueError)
|
||||||
|
self.assertIs(exc, e)
|
||||||
|
|
||||||
|
|
||||||
class ExceptHookTest(unittest.TestCase):
|
class ExceptHookTest(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Added the :meth:`sys.exception` method which returns the active exception instance.
|
|
@ -76,6 +76,28 @@ exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(sys_exception__doc__,
|
||||||
|
"exception($module, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Return the current exception.\n"
|
||||||
|
"\n"
|
||||||
|
"Return the most recent exception caught by an except clause\n"
|
||||||
|
"in the current stack frame or in an older stack frame, or None\n"
|
||||||
|
"if no such exception exists.");
|
||||||
|
|
||||||
|
#define SYS_EXCEPTION_METHODDEF \
|
||||||
|
{"exception", (PyCFunction)sys_exception, METH_NOARGS, sys_exception__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
sys_exception_impl(PyObject *module);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
sys_exception(PyObject *module, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
return sys_exception_impl(module);
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(sys_exc_info__doc__,
|
PyDoc_STRVAR(sys_exc_info__doc__,
|
||||||
"exc_info($module, /)\n"
|
"exc_info($module, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -992,4 +1014,4 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored))
|
||||||
#ifndef SYS_GETANDROIDAPILEVEL_METHODDEF
|
#ifndef SYS_GETANDROIDAPILEVEL_METHODDEF
|
||||||
#define SYS_GETANDROIDAPILEVEL_METHODDEF
|
#define SYS_GETANDROIDAPILEVEL_METHODDEF
|
||||||
#endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */
|
#endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */
|
||||||
/*[clinic end generated code: output=855fc93b2347710b input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=60756bc6f683e0c8 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -771,6 +771,28 @@ sys_excepthook_impl(PyObject *module, PyObject *exctype, PyObject *value,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
sys.exception
|
||||||
|
|
||||||
|
Return the current exception.
|
||||||
|
|
||||||
|
Return the most recent exception caught by an except clause
|
||||||
|
in the current stack frame or in an older stack frame, or None
|
||||||
|
if no such exception exists.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
sys_exception_impl(PyObject *module)
|
||||||
|
/*[clinic end generated code: output=2381ee2f25953e40 input=c88fbb94b6287431]*/
|
||||||
|
{
|
||||||
|
_PyErr_StackItem *err_info = _PyErr_GetTopmostException(_PyThreadState_GET());
|
||||||
|
if (err_info->exc_value != NULL) {
|
||||||
|
return Py_NewRef(err_info->exc_value);
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
sys.exc_info
|
sys.exc_info
|
||||||
|
|
||||||
|
@ -1963,6 +1985,7 @@ static PyMethodDef sys_methods[] = {
|
||||||
SYS__CURRENT_FRAMES_METHODDEF
|
SYS__CURRENT_FRAMES_METHODDEF
|
||||||
SYS__CURRENT_EXCEPTIONS_METHODDEF
|
SYS__CURRENT_EXCEPTIONS_METHODDEF
|
||||||
SYS_DISPLAYHOOK_METHODDEF
|
SYS_DISPLAYHOOK_METHODDEF
|
||||||
|
SYS_EXCEPTION_METHODDEF
|
||||||
SYS_EXC_INFO_METHODDEF
|
SYS_EXC_INFO_METHODDEF
|
||||||
SYS_EXCEPTHOOK_METHODDEF
|
SYS_EXCEPTHOOK_METHODDEF
|
||||||
SYS_EXIT_METHODDEF
|
SYS_EXIT_METHODDEF
|
||||||
|
@ -2457,7 +2480,8 @@ Functions:\n\
|
||||||
\n\
|
\n\
|
||||||
displayhook() -- print an object to the screen, and save it in builtins._\n\
|
displayhook() -- print an object to the screen, and save it in builtins._\n\
|
||||||
excepthook() -- print an exception and its traceback to sys.stderr\n\
|
excepthook() -- print an exception and its traceback to sys.stderr\n\
|
||||||
exc_info() -- return thread-safe information about the current exception\n\
|
exception() -- return the current thread's active exception\n\
|
||||||
|
exc_info() -- return information about the current thread's active exception\n\
|
||||||
exit() -- exit the interpreter by raising SystemExit\n\
|
exit() -- exit the interpreter by raising SystemExit\n\
|
||||||
getdlopenflags() -- returns flags to be used for dlopen() calls\n\
|
getdlopenflags() -- returns flags to be used for dlopen() calls\n\
|
||||||
getprofile() -- get the global profiling function\n\
|
getprofile() -- get the global profiling function\n\
|
||||||
|
|
Loading…
Reference in New Issue