[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