New PEP 490: Chain exceptions at C level
This commit is contained in:
parent
083f942a52
commit
022f78da88
|
@ -0,0 +1,172 @@
|
||||||
|
PEP: 490
|
||||||
|
Title: Chain exceptions at C level
|
||||||
|
Version: $Revision$
|
||||||
|
Last-Modified: $Date$
|
||||||
|
Author: Victor Stinner <victor.stinner@gmail.com>
|
||||||
|
Status: Draft
|
||||||
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
|
Created: 25-March-2015
|
||||||
|
Python-Version: 3.5
|
||||||
|
|
||||||
|
|
||||||
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
|
Python 3 chained exceptions: PEP 3134. This PEP makes the same change at C
|
||||||
|
level.
|
||||||
|
|
||||||
|
|
||||||
|
Rationale
|
||||||
|
=========
|
||||||
|
|
||||||
|
Python 3 chained exceptions: PEP 3134. This PEP makes the same change at C
|
||||||
|
level.
|
||||||
|
|
||||||
|
|
||||||
|
Proposal
|
||||||
|
========
|
||||||
|
|
||||||
|
Modify PyErr_*() funnctions to chain exceptions
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
Modify C functions raising exceptions of the Python C API to automatically
|
||||||
|
chain exceptions.
|
||||||
|
|
||||||
|
|
||||||
|
Modify functions to not chain exceptions
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
Keep the original exception is not always interesting. Example in Python
|
||||||
|
(``os._Environ.__getitem__``)::
|
||||||
|
|
||||||
|
try:
|
||||||
|
value = self._data[self.encodekey(key)]
|
||||||
|
except KeyError:
|
||||||
|
# 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).
|
||||||
|
|
||||||
|
|
||||||
|
Python C API
|
||||||
|
------------
|
||||||
|
|
||||||
|
Include/pyerror.h declares functions related to exceptions.
|
||||||
|
|
||||||
|
Functions raising exceptions:
|
||||||
|
|
||||||
|
* PyErr_SetNone(exc_type)
|
||||||
|
* PyErr_SetObject(exc_type, exc_value)
|
||||||
|
* PyErr_SetString(exc_type, message)
|
||||||
|
* PyErr_Format(exc, format, ...)
|
||||||
|
|
||||||
|
Helpers to raise specific exceptions:
|
||||||
|
|
||||||
|
* PyErr_BadArgument()
|
||||||
|
* PyErr_BadInternalCall()
|
||||||
|
* PyErr_NoMemory()
|
||||||
|
* PyErr_SetFromErrno(exc)
|
||||||
|
* PyErr_SetFromWindowsErr(err)
|
||||||
|
* PyErr_SetImportError(message, name, path)
|
||||||
|
* _PyErr_SetKeyError(key)
|
||||||
|
* _PyErr_TrySetFromCause(prefix_format, ...)
|
||||||
|
|
||||||
|
Manage the current exception:
|
||||||
|
|
||||||
|
* PyErr_Clear(): clear the current exception, like "except: pass"
|
||||||
|
* PyErr_Fetch(exc_type, exc_value, exc_tb)
|
||||||
|
* PyErr_Restore(exc_type, exc_value, exc_tb)
|
||||||
|
* PyErr_GetExcInfo(exc_type, exc_value, exc_tb)
|
||||||
|
* PyErr_SetExcInfo(exc_type, exc_value, exc_tb)
|
||||||
|
|
||||||
|
Others function to handle exceptions:
|
||||||
|
|
||||||
|
* PyErr_ExceptionMatches(exc): check to implement "except exc: ..."
|
||||||
|
* PyErr_GivenExceptionMatches(exc1, exc2)
|
||||||
|
* PyErr_NormalizeException(exc_type, exc_value, exc_tb)
|
||||||
|
* _PyErr_ChainExceptions(exc_type, exc_value, exc_tb)
|
||||||
|
|
||||||
|
|
||||||
|
Backward compatibility
|
||||||
|
======================
|
||||||
|
|
||||||
|
XXX
|
||||||
|
|
||||||
|
|
||||||
|
Alternatives
|
||||||
|
============
|
||||||
|
|
||||||
|
No change
|
||||||
|
---------
|
||||||
|
|
||||||
|
Python 3.5 introduces a new private ``_PyErr_ChainExceptions()`` function which
|
||||||
|
is enough to chain manually exceptions.
|
||||||
|
|
||||||
|
|
||||||
|
New helpers to chain exceptions
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Functions like ``PyErr_SetString()`` don't chain automatically exceptions. To
|
||||||
|
make usage of ``_PyErr_ChainExceptions()`` easier, new functions are added:
|
||||||
|
|
||||||
|
* PyErr_SetStringChain(exc_type, message)
|
||||||
|
* PyErr_FormatChaine(exc_type, format, ...)
|
||||||
|
* PyErr_SetNoneChain(exc_type)
|
||||||
|
* PyErr_SetObjectChain(exc_type, exc_value)
|
||||||
|
|
||||||
|
Helper functions like _PyErr_SetKeyError(key) or PyErr_SetImportError(message,
|
||||||
|
name, path) don't chain exceptions. The generic
|
||||||
|
_PyErr_ChainExceptions(exc_type, exc_value, exc_tb) should be used.
|
||||||
|
|
||||||
|
|
||||||
|
Appendix
|
||||||
|
========
|
||||||
|
|
||||||
|
Python Issues
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Chain exceptions:
|
||||||
|
|
||||||
|
* `Chain exceptions in C
|
||||||
|
<http://bugs.python.org/issue23763>`_
|
||||||
|
* `Chaining exceptions at C level
|
||||||
|
<http://bugs.python.org/issue21715>`_: added _PyErr_ChainExceptions()
|
||||||
|
* `zipimport: chain ImportError to OSError
|
||||||
|
<http://bugs.python.org/issue23696>`_
|
||||||
|
|
||||||
|
Prevent loosing exceptions:
|
||||||
|
|
||||||
|
* `Raise SystemError if a function returns a result with an exception set
|
||||||
|
<http://bugs.python.org/issue23571>`_
|
||||||
|
|
||||||
|
|
||||||
|
PEPs
|
||||||
|
----
|
||||||
|
|
||||||
|
* `PEP 3134 -- Exception Chaining and Embedded Tracebacks
|
||||||
|
<https://www.python.org/dev/peps/pep-3134/>`_ (Python 3.0):
|
||||||
|
new ``__context__`` and ``__cause__`` attributes for exceptions
|
||||||
|
* `PEP 415 - Implement context suppression with exception attributes
|
||||||
|
<https://www.python.org/dev/peps/pep-0415/>`_ (Python 3.3):
|
||||||
|
``raise exc from None``
|
||||||
|
* `PEP 409 - Suppressing exception context
|
||||||
|
<https://www.python.org/dev/peps/pep-0409/>`_ (superseded by the PEP 415)
|
||||||
|
|
||||||
|
|
||||||
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
..
|
||||||
|
Local Variables:
|
||||||
|
mode: indented-text
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
sentence-end-double-space: t
|
||||||
|
fill-column: 70
|
||||||
|
coding: utf-8
|
||||||
|
End:
|
Loading…
Reference in New Issue