[Python-checkins] peps: PEP 490

victor.stinner python-checkins at python.org
Thu Mar 26 11:14:56 CET 2015


https://hg.python.org/peps/rev/cece102fa4b9
changeset:   5743:cece102fa4b9
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Thu Mar 26 11:14:48 2015 +0100
summary:
  PEP 490

files:
  pep-0490.txt |  123 +++++++++++++++++++++++++++++++++++---
  1 files changed, 112 insertions(+), 11 deletions(-)


diff --git a/pep-0490.txt b/pep-0490.txt
--- a/pep-0490.txt
+++ b/pep-0490.txt
@@ -13,22 +13,46 @@
 Abstract
 ========
 
-Python 3 chained exceptions: PEP 3134. This PEP makes the same change at C
-level.
+Chain exceptions at C level, as already done at Python level.
 
 
 Rationale
 =========
 
-Python 3 chained exceptions: PEP 3134. This PEP makes the same change at C
-level.
+Python 3 introduced a new killer feature: exceptions are chained by default,
+PEP 3134.
+
+Example::
+
+    try:
+        raise TypeError("err1")
+    except TypeError:
+        raise ValueError("err2")
+
+Output::
+
+    Traceback (most recent call last):
+      File "test.py", line 2, in <module>
+        raise TypeError("err1")
+    TypeError: err1
+
+    During handling of the above exception, another exception occurred:
+
+    Traceback (most recent call last):
+      File "test.py", line 4, in <module>
+        raise ValueError("err2")
+    ValueError: err2
+
+Exceptions are chained by default in Python code, but not in extensions written
+in C. This PEP proposes to also chain exceptions automatically at C level to
+stay consistent.
 
 
 Proposal
 ========
 
-Modify PyErr_*() funnctions to chain exceptions
------------------------------------------------
+Modify PyErr_*() functions to chain exceptions
+----------------------------------------------
 
 Modify C functions raising exceptions of the Python C API to automatically
 chain exceptions.
@@ -37,8 +61,12 @@
 Modify functions to not chain exceptions
 ----------------------------------------
 
-Keep the original exception is not always interesting. Example in Python
-(``os._Environ.__getitem__``)::
+To remove the previous exception, PyErr_Clear() can be called before
+PyErr_SetString() (or other functions raising exceptions).
+
+Keeping the original exception is not always interesting.
+
+Example of Python code (``os._Environ.__getitem__``) suppressing the context::
 
     try:
         value = self._data[self.encodekey(key)]
@@ -46,8 +74,63 @@
         # raise KeyError with the original key value
         raise KeyError(key) from None
 
-To remove the previous exception, PyErr_Clear() can be called before
-PyErr_SetString() (or other functions raising exceptions).
+Example of an exception chain raised by the struct module with exceptions
+chained by default::
+
+    $ python3.5 -c 'import struct; struct.pack("b", 2**100)'
+    OverflowError: Python int too large to convert to C long
+
+    During handling of the above exception, another exception occurred:
+
+    Traceback (most recent call last):
+      File "<string>", line 1, in <module>
+    struct.error: argument out of range
+
+The ``OverflowError`` exception is not very useful, it can be hidden.
+
+
+Modify functions to chain exceptions
+------------------------------------
+
+Some functions save and then restore the current exception. If a new exception
+is raised, the exception is displayed or ignored depending on the function.
+
+Maybe some of these functions should be modified to chain exceptions instead?
+
+Examples of function displaying the new exception:
+
+* atexit_callfuncs(): display exceptions with PyErr_Display() and return the
+  latest exception
+* sock_dealloc(): log warning exception with PyErr_WriteUnraisable()
+* slot_tp_del(): display exception with PyErr_WriteUnraisable()
+* _PyGen_Finalize(): display gen_close() exception with PyErr_WriteUnraisable()
+* slot_tp_finalize(): display exception raised by __del__() with
+  PyErr_WriteUnraisable()
+* PyErr_GivenExceptionMatches(): display exception raised by PyType_IsSubtype()
+  with PyErr_WriteUnraisable()
+
+Examples of function ignoring the new exception(s):
+
+* ptrace_enter_call(): ignore exception
+* subprocess_fork_exec(): ignore exception raised by enable_gc()
+* t_bootstrap() of the _thread module: ignore raised exception when trying to
+  display the bootstrap function to sys.stderr
+* PyDict_GetItem(), _PyDict_GetItem_KnownHash(): ignore exception raiesd when
+  looking for a key
+* _PyErr_TrySetFromCause(): ignore ecxeption
+* PyFrame_LocalsToFast(): ignore exception raised by dict_to_map()
+* _PyObject_Dump(): ignore exception. _PyObject_Dump() is used to debug, to
+  inspect a running process, it should not modify the Python state.
+* Py_ReprLeave(): ignore exception "because there is no way to report them"
+* type_dealloc(): ignore exception raised by remove_all_subclasses()
+* PyObject_ClearWeakRefs(): ignore exceptions?
+* call_exc_trace(), call_trace_protected(): ignore exception
+* remove_importlib_frames(): ignore exception
+* do_mktuple(), helped used by Py_BuildValue() for example: ignore exception?
+* flush_io(): ignore exception
+* sys_write(), sys_format(): ignore exception
+* _PyTraceback_Add(): ignore exception
+* PyTraceBack_Print(): ignore exception
 
 
 Python C API
@@ -92,7 +175,20 @@
 Backward compatibility
 ======================
 
-XXX
+A side effect of chaining exceptions is that exceptions store traceback
+objects. Traceback objects store frame objects which store local variables.
+Local variables are kept alive by exceptions. A common issue is a reference
+cycle between local variables and exceptions. The cycle only impacts
+applications storing exceptions.
+
+The reference cycle can now be fixed with the new traceback.TracebackException
+object introduced in Python 3.5 which store informations required to format a
+full textual traceback without storing local variables.
+
+The asyncio is impacted by the reference cycle issue, but this module is also
+maintained outside Python standard library to release a version for Python 3.3.
+traceback.TracebackException will probably be backward in a private asyncio
+module to fix the issue.
 
 
 Alternatives
@@ -135,6 +231,11 @@
   <http://bugs.python.org/issue23696>`_
 * `Issue #21715: Chaining exceptions at C level
   <http://bugs.python.org/issue21715>`_: added _PyErr_ChainExceptions()
+* `Issue #18488: sqlite: finalize() method of user function may be called with
+  an exception set if a call to step() method failed
+  <http://bugs.python.org/issue18488>`_
+* `Issue #23781: Add private _PyErr_ReplaceException() in 2.7
+  <http://bugs.python.org/issue23781>`_
 
 Changes preventing loosing exceptions:
 

-- 
Repository URL: https://hg.python.org/peps


More information about the Python-checkins mailing list