PEP: 490 Title: Chain exceptions at C level Version: $Revision$ Last-Modified: $Date$ Author: Victor Stinner 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: * `Issue #23763: Chain exceptions in C `_ * `Issue #23696: zipimport: chain ImportError to OSError `_ * `Issue #21715: Chaining exceptions at C level `_: added _PyErr_ChainExceptions() Changes preventing loosing exceptions: * `Issue #23571: Raise SystemError if a function returns a result with an exception set `_ * `Issue #18408: Fixes crashes found by pyfailmalloc `_ PEPs ---- * `PEP 3134 -- Exception Chaining and Embedded Tracebacks `_ (Python 3.0): new ``__context__`` and ``__cause__`` attributes for exceptions * `PEP 415 - Implement context suppression with exception attributes `_ (Python 3.3): ``raise exc from None`` * `PEP 409 - Suppressing exception context `_ (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: