8000 bpo-46328: Add sys.exception() (GH-30514) · python/cpython@c590b58 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c590b58

Browse files
authored
bpo-46328: Add sys.exception() (GH-30514)
1 parent 9c2ebb9 commit c590b58

File tree

7 files changed

+146
-18
lines changed

7 files changed

+146
-18
lines changed

Doc/library/sys.rst

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -378,26 +378,41 @@ always available.
378378
.. versionadded:: 3.8
379379
__unraisablehook__
380380

381+
382+
.. function:: exception()
383+
384+
This function returns the exception instance that is currently being
385+
handled. This exception is specific both to the current thread and
386+
to the current stack frame. If the current stack frame is not handling
387+
an exception, the exception is taken from the calling stack frame, or its
388+
caller, and so on until a stack frame is found that is handling an
389+
exception. Here, "handling an exception" is defined as "executing an
390+
except clause." For any stack frame, only the exception being currently
391+
handled is accessible.
392+
393+
.. index:: object: traceback
394+
395+
If no exception is being handled anywhere on the stack, ``None`` is
396+
returned.
397+
398+
.. versionadded:: 3.11
399+
400+
381401
.. function:: exc_info()
382402

383-
This function returns a tuple of three values that give information about the
384-
exception that is currently being handled. The information returned is specific
385-
both to the current thread and to the current stack frame. If the current stack
386-
frame is not handling an exception, the information is taken from the calling
387-
stack frame, or its caller, and so on until a stack frame is found that is
388-
handling an exception. Here, "handling an exception" is defined as "executing
389-
an except clause." For any stack frame, only information about the exception
390-
being currently handled is accessible.
403+
This function returns the old-style representation of the handled
404+
exception. If an exception ``e`` is currently handled (so
405+
:func:`exception` would return ``e``), :func:`exc_info` returns the
406+
tuple ``(type(e), e, e.__traceback__)``.
407+
That is, a tuple containing the type of the exception (a subclass of
408+
:exc:`BaseException`), the exception itself, and a :ref:`traceback
409+
object <traceback-objects>` which typically encapsulates the call
410+
stack at the point where the exception last occurred.
391411

392412
.. index:: object: traceback
393413

394-
If no exception is being handled anywhere on the stack, a tuple containing
395-
three ``None`` values is returned. Otherwise, the values returned are
396-
``(type, value, traceback)``. Their meaning is: *type* gets the type of the
397-
exception being handled (a subclass of :exc:`BaseException`); *value* gets
398-
the exception instance (an instance of the exception type); *traceback* gets
399-
a :ref:`traceback object <traceback-objects>` which typically encapsulates
400-
the call stack at the point where the exception last occurred.
414+
If no exception is being handled anywhere on the stack, this function
415+
return a tuple containing three ``None`` values.
401416

402417
.. versionchanged:: 3.11
403418
The ``type`` and ``traceback`` fields are now derived from the ``value``

Doc/tutorial/errors.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ then re-raise the exception (allowing a caller to handle the exception as well):
167167
raise
168168

169169
Alternatively the last except clause may omit the exception name(s), however the exception
170-
value must then be retrieved from ``sys.exc_info()[1]``.
170+
value must then be retrieved with ``sys.exception()``.
171171

172172
The :keyword:`try` ... :keyword:`except` statement has an optional *else
173173
clause*, which, when present, must follow all *except clauses*. It is useful

Doc/whatsnew/3.11.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,9 @@ sys
305305
the results of subsequent calls to :func:`exc_info`.
306306
(Contributed by Irit Katriel in :issue:`45711`.)
307307

308+
* Add :func:`sys.exception` which returns the active exception instance
309+
(equivalent to ``sys.exc_info()[1]``).
310+
(Contributed by Irit Katriel in :issue:`46328`.)
308311

309312
threading
310313
---------

Lib/test/test_sys.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,69 @@ def baddisplayhook(obj):
7171
code = compile("42", "<string>", "single")
7272
self.assertRaises(ValueError, eval, code)
7373

74+
class ActiveExceptionTests(unittest.TestCase):
75+
def test_exc_info_no_exception(self):
76+
self.assertEqual(sys.exc_info(), (None, None, None))
77+
78+
def test_sys_exception_no_exception(self):
79+
self.assertEqual(sys.exception(), None)
80+
81+
def test_exc_info_with_exception_instance(self):
82+
def f():
83+
raise ValueError(42)
84+
85+
try:
86+
f()
87+
except Exception as e_:
88+
e = e_
89+
exc_info = sys.exc_info()
90+
91+
self.assertIsInstance(e, ValueError)
92+
self.assertIs(exc_info[0], ValueError)
93+
self.assertIs(exc_info[1], e)
94+
self.assertIs(exc_info[2], e.__traceback__)
95+
96+
def test_exc_info_with_exception_type(self):
97+
def f():
98+
raise ValueError
99+
100+
try:
101+
f()
102+
except Exception as e_:
103+
e = e_
104+
exc_info = sys.exc_info()
105+
106+
self.assertIsInstance(e, ValueError)
107+
self.assertIs(exc_info[0], ValueError)
108+
self.assertIs(exc_info[1], e)
109+
self.assertIs(exc_info[2], e.__traceback__)
110+
111+
def test_sys_exception_with_exception_instance(self):
112+
def f():
113+
raise ValueError(42)
114+
115+
try:
116+
f()
117+
except Exception as e_:
118+
e = e_
119+
exc = sys.exception()
120+
121+
self.assertIsInstance(e, ValueError)
122+
self.assertIs(exc, e)
123+
124+
def test_sys_exception_with_exception_type(self):
125+
def f():
126+
raise ValueError
127+
128+
try:
129+
f()
130+
except Exception as e_:
131+
e = e_
132+
exc = sys.exception()
133+
134+
self.assertIsInstance(e, ValueError)
135+
self.assertIs(exc, e)
136+
74137

75138
class ExceptHookTest(unittest.TestCase):
76139

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added the :meth:`sys.exception` method which returns the active exception instance.

Python/clinic/sysmodule.c.h

Lines changed: 23 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/sysmodule.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,28 @@ sys_excepthook_impl(PyObject *module, PyObject *exctype, PyObject *value,
771771
}
772772

773773

774+
/*[clinic input]
775+
sys.exception
776+
777+
Return the current exception.
778+
779+
Return the most recent exception caught by an except clause
780+
in the current stack frame or in an older stack frame, or None
781+
if no such exception exists.
782+
[clinic start generated code]*/
783+
784+
static PyObject *
785+
sys_exception_impl(PyObject *module)
786+
/*[clinic end generated code: output=2381ee2f25953e40 input=c88fbb94b6287431]*/
787+
{
788+
_PyErr_StackItem *err_info = _PyErr_GetTopmostException(_PyThreadState_GET());
789+
if (err_info->exc_value != NULL) {
790+
return Py_NewRef(err_info->exc_value);
791+
}
792+
Py_RETURN_NONE;
793+
}
794+
795+
774796
/*[clinic input]
775797
sys.exc_info
776798
@@ -1963,6 +1985,7 @@ static PyMethodDef sys_methods[] = {
19631985
SYS__CURRENT_FRAMES_METHODDEF
19641986
SYS__CURRENT_EXCEPTIONS_METHODDEF
19651987
SYS_DISPLAYHOOK_METHODDEF
1988+
SYS_EXCEPTION_METHODDEF
19661989
SYS_EXC_INFO_METHODDEF
19671990
SYS_EXCEPTHOOK_METHODDEF
19681991
SYS_EXIT_METHODDEF
@@ -2457,7 +2480,8 @@ Functions:\n\
24572480
\n\
24582481
displayhook() -- print an object to the screen, and save it in builtins._\n\
24592482
excepthook() -- print an exception and its traceback to sys.stderr\n\
2460-
exc_info() -- return thread-safe information about the current exception\n\
2483+
exception() -- return the current thread's active exception\n\
2484+
exc_info() -- return information about the current thread's active exception\n\
24612485
exit() -- exit the interpreter by raising SystemExit\n\
24622486
getdlopenflags() -- returns flags to be used for dlopen() calls\n\
24632487
getprofile() -- get the global profiling function\n\

0 commit comments

Comments
 (0)
0