mirror of
https://github.com/python/cpython.git
synced 2025-07-23 19:25:40 +00:00
- New function sys.exc_clear() clears the current exception. This is
rarely needed, but can sometimes be useful to release objects referenced by the traceback held in sys.exc_info()[2]. (SF patch #693195.) Thanks to Kevin Jacobs!
This commit is contained in:
parent
d1a283be26
commit
46d3dc37e4
5 changed files with 116 additions and 12 deletions
|
@ -99,6 +99,11 @@ It is always available.
|
||||||
encapsulates the call stack at the point where the exception
|
encapsulates the call stack at the point where the exception
|
||||||
originally occurred. \obindex{traceback}
|
originally occurred. \obindex{traceback}
|
||||||
|
|
||||||
|
If \function{exc_clear()} is called, this function will return three
|
||||||
|
\code{None} values until either another exception is raised in the
|
||||||
|
current thread or the execution stack returns to a frame where
|
||||||
|
another exception is being handled.
|
||||||
|
|
||||||
\warning{Assigning the \var{traceback} return value to a
|
\warning{Assigning the \var{traceback} return value to a
|
||||||
local variable in a function that is handling an exception will
|
local variable in a function that is handling an exception will
|
||||||
cause a circular reference. This will prevent anything referenced
|
cause a circular reference. This will prevent anything referenced
|
||||||
|
@ -115,6 +120,21 @@ It is always available.
|
||||||
efficient to avoid creating cycles.}
|
efficient to avoid creating cycles.}
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
|
\begin{funcdesc}{exc_clear}{}
|
||||||
|
This function clears all information relating to the current or last
|
||||||
|
exception that occured in the current thread. After calling this
|
||||||
|
function, \function{exc_info()} will return three \code{None} values until
|
||||||
|
another exception is raised in the current thread or the execution stack
|
||||||
|
returns to a frame where another exception is being handled.
|
||||||
|
|
||||||
|
This function is only needed in only a few obscure situations. These
|
||||||
|
include logging and error handling systems that report information on the
|
||||||
|
last or current exception. This function can also be used to try to free
|
||||||
|
resources and trigger object finalization, though no guarantee is made as
|
||||||
|
to what objects will be freed, if any.
|
||||||
|
\versionadded{2.3}
|
||||||
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{datadesc}{exc_type}
|
\begin{datadesc}{exc_type}
|
||||||
\dataline{exc_value}
|
\dataline{exc_value}
|
||||||
\dataline{exc_traceback}
|
\dataline{exc_traceback}
|
||||||
|
|
|
@ -2451,14 +2451,15 @@ a module defines. It returns a sorted list of strings:
|
||||||
['__name__', 'fib', 'fib2']
|
['__name__', 'fib', 'fib2']
|
||||||
>>> dir(sys)
|
>>> dir(sys)
|
||||||
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',
|
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',
|
||||||
'__stdin__', '__stdout__', '_getframe', 'argv', 'builtin_module_names',
|
'__stdin__', '__stdout__', '_getframe', 'api_version', 'argv',
|
||||||
'byteorder', 'copyright', 'displayhook', 'exc_info', 'exc_type',
|
'builtin_module_names', 'byteorder', 'callstats', 'copyright',
|
||||||
'excepthook', 'exec_prefix', 'executable', 'exit', 'getdefaultencoding',
|
'displayhook', 'exc_clear', 'exc_info', 'exc_type', 'excepthook',
|
||||||
'getdlopenflags', 'getrecursionlimit', 'getrefcount', 'hexversion',
|
'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags',
|
||||||
'maxint', 'maxunicode', 'modules', 'path', 'platform', 'prefix', 'ps1',
|
'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode',
|
||||||
'ps2', 'setcheckinterval', 'setdlopenflags', 'setprofile',
|
'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache',
|
||||||
'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version',
|
'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags',
|
||||||
'version_info', 'warnoptions']
|
'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout',
|
||||||
|
'version', 'version_info', 'warnoptions']
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
|
|
||||||
Without arguments, \function{dir()} lists the names you have defined
|
Without arguments, \function{dir()} lists the names you have defined
|
||||||
|
|
|
@ -63,6 +63,50 @@ class SysModuleTest(unittest.TestCase):
|
||||||
# FIXME: testing the code for a lost or replaced excepthook in
|
# FIXME: testing the code for a lost or replaced excepthook in
|
||||||
# Python/pythonrun.c::PyErr_PrintEx() is tricky.
|
# Python/pythonrun.c::PyErr_PrintEx() is tricky.
|
||||||
|
|
||||||
|
def test_exc_clear(self):
|
||||||
|
self.assertRaises(TypeError, sys.exc_clear, 42)
|
||||||
|
|
||||||
|
# Verify that exc_info is present and matches exc, then clear it, and
|
||||||
|
# check that it worked.
|
||||||
|
def clear_check(exc):
|
||||||
|
typ, value, traceback = sys.exc_info()
|
||||||
|
self.assert_(typ is not None)
|
||||||
|
self.assert_(value is exc)
|
||||||
|
self.assert_(traceback is not None)
|
||||||
|
|
||||||
|
sys.exc_clear()
|
||||||
|
|
||||||
|
typ, value, traceback = sys.exc_info()
|
||||||
|
self.assert_(typ is None)
|
||||||
|
self.assert_(value is None)
|
||||||
|
self.assert_(traceback is None)
|
||||||
|
|
||||||
|
def clear():
|
||||||
|
try:
|
||||||
|
raise ValueError, 42
|
||||||
|
except ValueError, exc:
|
||||||
|
clear_check(exc)
|
||||||
|
|
||||||
|
# Raise an exception and check that it can be cleared
|
||||||
|
clear()
|
||||||
|
|
||||||
|
# Verify that a frame currently handling an exception is
|
||||||
|
# unaffected by calling exc_clear in a nested frame.
|
||||||
|
try:
|
||||||
|
raise ValueError, 13
|
||||||
|
except ValueError, exc:
|
||||||
|
typ1, value1, traceback1 = sys.exc_info()
|
||||||
|
clear()
|
||||||
|
typ2, value2, traceback2 = sys.exc_info()
|
||||||
|
|
||||||
|
self.assert_(typ1 is typ2)
|
||||||
|
self.assert_(value1 is exc)
|
||||||
|
self.assert_(value1 is value2)
|
||||||
|
self.assert_(traceback1 is traceback2)
|
||||||
|
|
||||||
|
# Check that an exception can be cleared outside of an except block
|
||||||
|
clear_check(exc)
|
||||||
|
|
||||||
def test_exit(self):
|
def test_exit(self):
|
||||||
self.assertRaises(TypeError, sys.exit, 42, 42)
|
self.assertRaises(TypeError, sys.exit, 42, 42)
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,12 @@ What's New in Python 2.3 beta 1?
|
||||||
Core and builtins
|
Core and builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|
||||||
|
- New function sys.exc_clear() clears the current exception. This is
|
||||||
|
rarely needed, but can sometimes be useful to release objects
|
||||||
|
referenced by the traceback held in sys.exc_info()[2]. (SF patch
|
||||||
|
#693195.)
|
||||||
|
|
||||||
- On 64-bit systems, a dictionary could contain duplicate long/int keys
|
- On 64-bit systems, a dictionary could contain duplicate long/int keys
|
||||||
if the key value was larger than 2**32. See SF bug #689659.
|
if the key value was larger than 2**32. See SF bug #689659.
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ PyDoc_STRVAR(excepthook_doc,
|
||||||
);
|
);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sys_exc_info(PyObject *self)
|
sys_exc_info(PyObject *self, PyObject *noargs)
|
||||||
{
|
{
|
||||||
PyThreadState *tstate;
|
PyThreadState *tstate;
|
||||||
tstate = PyThreadState_Get();
|
tstate = PyThreadState_Get();
|
||||||
|
@ -147,8 +147,39 @@ sys_exc_info(PyObject *self)
|
||||||
PyDoc_STRVAR(exc_info_doc,
|
PyDoc_STRVAR(exc_info_doc,
|
||||||
"exc_info() -> (type, value, traceback)\n\
|
"exc_info() -> (type, value, traceback)\n\
|
||||||
\n\
|
\n\
|
||||||
Return information about the exception that is currently being handled.\n\
|
Return information about the most recent exception caught by an except\n\
|
||||||
This should be called from inside an except clause only."
|
clause in the current stack frame or in an older stack frame."
|
||||||
|
);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
sys_exc_clear(PyObject *self, PyObject *noargs)
|
||||||
|
{
|
||||||
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
|
PyObject *tmp_type, *tmp_value, *tmp_tb;
|
||||||
|
tmp_type = tstate->exc_type;
|
||||||
|
tmp_value = tstate->exc_value;
|
||||||
|
tmp_tb = tstate->exc_traceback;
|
||||||
|
tstate->exc_type = NULL;
|
||||||
|
tstate->exc_value = NULL;
|
||||||
|
tstate->exc_traceback = NULL;
|
||||||
|
Py_XDECREF(tmp_type);
|
||||||
|
Py_XDECREF(tmp_value);
|
||||||
|
Py_XDECREF(tmp_tb);
|
||||||
|
/* For b/w compatibility */
|
||||||
|
PySys_SetObject("exc_type", Py_None);
|
||||||
|
PySys_SetObject("exc_value", Py_None);
|
||||||
|
PySys_SetObject("exc_traceback", Py_None);
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(exc_clear_doc,
|
||||||
|
"exc_clear() -> None\n\
|
||||||
|
\n\
|
||||||
|
Clear global information on the current exception. Subsequent calls to\n\
|
||||||
|
exc_info() will return (None,None,None) until another exception is raised\n\
|
||||||
|
in the current thread or the execution stack returns to a frame where\n\
|
||||||
|
another exception is being handled."
|
||||||
);
|
);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -600,7 +631,8 @@ static PyMethodDef sys_methods[] = {
|
||||||
{"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS,
|
{"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS,
|
||||||
callstats_doc},
|
callstats_doc},
|
||||||
{"displayhook", sys_displayhook, METH_O, displayhook_doc},
|
{"displayhook", sys_displayhook, METH_O, displayhook_doc},
|
||||||
{"exc_info", (PyCFunction)sys_exc_info, METH_NOARGS, exc_info_doc},
|
{"exc_info", sys_exc_info, METH_NOARGS, exc_info_doc},
|
||||||
|
{"exc_clear", sys_exc_clear, METH_NOARGS, exc_clear_doc},
|
||||||
{"excepthook", sys_excepthook, METH_VARARGS, excepthook_doc},
|
{"excepthook", sys_excepthook, METH_VARARGS, excepthook_doc},
|
||||||
{"exit", sys_exit, METH_VARARGS, exit_doc},
|
{"exit", sys_exit, METH_VARARGS, exit_doc},
|
||||||
#ifdef Py_USING_UNICODE
|
#ifdef Py_USING_UNICODE
|
||||||
|
@ -786,6 +818,7 @@ Functions:\n\
|
||||||
displayhook() -- print an object to the screen, and save it in __builtin__._\n\
|
displayhook() -- print an object to the screen, and save it in __builtin__._\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\
|
exc_info() -- return thread-safe information about the current exception\n\
|
||||||
|
exc_clear() -- clear the exception state for the current thread\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\
|
||||||
getrefcount() -- return the reference count for an object (plus one :-)\n\
|
getrefcount() -- return the reference count for an object (plus one :-)\n\
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue