- 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:
Guido van Rossum 2003-03-01 03:20:41 +00:00
parent d1a283be26
commit 46d3dc37e4
5 changed files with 116 additions and 12 deletions

View File

@ -99,6 +99,11 @@ It is always available.
encapsulates the call stack at the point where the exception
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
local variable in a function that is handling an exception will
cause a circular reference. This will prevent anything referenced
@ -115,6 +120,21 @@ It is always available.
efficient to avoid creating cycles.}
\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}
\dataline{exc_value}
\dataline{exc_traceback}

View File

@ -2451,14 +2451,15 @@ a module defines. It returns a sorted list of strings:
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',
'__stdin__', '__stdout__', '_getframe', 'argv', 'builtin_module_names',
'byteorder', 'copyright', 'displayhook', 'exc_info', 'exc_type',
'excepthook', 'exec_prefix', 'executable', 'exit', 'getdefaultencoding',
'getdlopenflags', 'getrecursionlimit', 'getrefcount', 'hexversion',
'maxint', 'maxunicode', 'modules', 'path', 'platform', 'prefix', 'ps1',
'ps2', 'setcheckinterval', 'setdlopenflags', 'setprofile',
'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version',
'version_info', 'warnoptions']
'__stdin__', '__stdout__', '_getframe', 'api_version', 'argv',
'builtin_module_names', 'byteorder', 'callstats', 'copyright',
'displayhook', 'exc_clear', 'exc_info', 'exc_type', 'excepthook',
'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags',
'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode',
'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache',
'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags',
'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout',
'version', 'version_info', 'warnoptions']
\end{verbatim}
Without arguments, \function{dir()} lists the names you have defined

View File

@ -63,6 +63,50 @@ class SysModuleTest(unittest.TestCase):
# FIXME: testing the code for a lost or replaced excepthook in
# 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):
self.assertRaises(TypeError, sys.exit, 42, 42)

View File

@ -12,6 +12,12 @@ What's New in Python 2.3 beta 1?
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
if the key value was larger than 2**32. See SF bug #689659.

View File

@ -132,7 +132,7 @@ PyDoc_STRVAR(excepthook_doc,
);
static PyObject *
sys_exc_info(PyObject *self)
sys_exc_info(PyObject *self, PyObject *noargs)
{
PyThreadState *tstate;
tstate = PyThreadState_Get();
@ -147,8 +147,39 @@ sys_exc_info(PyObject *self)
PyDoc_STRVAR(exc_info_doc,
"exc_info() -> (type, value, traceback)\n\
\n\
Return information about the exception that is currently being handled.\n\
This should be called from inside an except clause only."
Return information about the most recent exception caught by an except\n\
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 *
@ -600,7 +631,8 @@ static PyMethodDef sys_methods[] = {
{"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS,
callstats_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},
{"exit", sys_exit, METH_VARARGS, exit_doc},
#ifdef Py_USING_UNICODE
@ -786,6 +818,7 @@ Functions:\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\
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\
getdlopenflags() -- returns flags to be used for dlopen() calls\n\
getrefcount() -- return the reference count for an object (plus one :-)\n\