]> granicus.if.org Git - python/commitdiff
- New function sys.exc_clear() clears the current exception. This is
authorGuido van Rossum <guido@python.org>
Sat, 1 Mar 2003 03:20:41 +0000 (03:20 +0000)
committerGuido van Rossum <guido@python.org>
Sat, 1 Mar 2003 03:20:41 +0000 (03:20 +0000)
  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!

Doc/lib/libsys.tex
Doc/tut/tut.tex
Lib/test/test_sys.py
Misc/NEWS
Python/sysmodule.c

index 3f8f7b6a777de18de9b08e3aefbf8d7996e9ea81..d027aa62ac7081321784cabc0a079e8990aec327 100644 (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}
index cfc56f0922201e14f6e7656dfaba40e358f8d69b..a9fb325fb9a02bbe8d494f9927c947879f052fde 100644 (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
index b18b0c7761c2ace9c88fe59c6a7352b1c9dc9f86..2afac653ef0336d7ce618bb7f98a41c802d40cfe 100644 (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)
 
index 678b783736fc90efa0655cb746887695aaefe3e3..5405ce54b1d5b43412e26c0a19beb58754d83201 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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.
 
index 1f51f988f9e8abd317c971527523441a3c669266..13b86f2270bc6017f1fc4ce031378a116c029c77 100644 (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\