Last active
January 11, 2022 01:49
-
-
Save iritkatriel/3927147548b10a7929cb0b680e3adc52 to your computer and use it in GitHub Desktop.
Towards removing the exc_info triplet from Python's API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Following recent work [https://bugs.python.org/issue45711], the interpreter's internal | |
representation of the active exception (sys.exc_info()) is no longer the (typ, val, tb) | |
triplet, but just the exception instance. | |
For backward compatibility, existing APIs reconstruct the triplet from the instance, so | |
for example ``sys.exc_info()`` returns the triplet ``(type(exc), exc, exc.__traceback__)``, | |
where ``exc`` is the active exception. | |
Removing the triplet representation entirely is not something we can realistically | |
do anytime soon. However, it is feasible to reach a state where the triplet need not | |
show up in new python code, making the language simpler and removing some redundancy. | |
Below I am collecting a list of the changes required to achieve that. We don't have | |
to do all of them, and we certainly don't have to do all at once. | |
1. Getters/setters for the active exception | |
In python, we have sys.exc_info() and in the C api we have both PyErr_GetExcInfo | |
and PyErr_SetExcInfo. We will need alternatives that get/set a single exception | |
instance rather than the tuple. Proposed names: | |
sys.exception() (as suggested in PEP 3134) | |
PyErr_GetActiveExc() / PyErr_SetActiveExc() | |
The reason that we need to specify "Active" in the names in the C api but not in python | |
is because in the C api we can also access the interpreter's error indicator (i.e., the | |
in-flight exception) via PyErr_Fetch/Restore. | |
On the other hand, from Python code it is only possible to access the active exception. | |
(By definition, the error indicator is never set when python code is executing). | |
2. stdlib APIs that accept a (typ, val, tb) triplet representing an exception: | |
These APIs can be made versatile, as was already done in the traceback | |
[https://bugs.python.org/issue26389] and logging [https://bugs.python.org/issue20537] | |
modules. We would need to similarly update also: | |
In unittest.result, methods like addError, addFailure, etc accept the exc_info tuple. | |
They will need to accept an exc as well. | |
3. callback signatures | |
The exc_info is in the signatures of a few callbacks that the interpreter calls: | |
1. sys.excepthook(typ, val, tb) | |
2. __exit__/__aexit__(self, typ, val, tb) methods of context managers | |
In both of the above cases we would like to support the same callback | |
with a simplified signature: sys.excepthook(exc) and __exit__(self, exc). | |
This will require inspection of the signature of the callback, to find out | |
how many arguments it expects and call with exc or exc_info accordingly. | |
This is fairly straightforward in python, but in the C api I don't think | |
this is currently formalized, so we need to add some kind of introspection | |
API for callables (or maybe not all callables, just methods and functions, | |
and assume that any other callable has the legacy API, then document the | |
restrictions). | |
This appears to be the most technically complicated item in this list, but | |
I think the ergonomic gain of simplifying the __exit__ signature may well | |
be worth it. | |
3. Lib/shutil methods accept an onerror callback that accepts the exc_info | |
tuple as one of its args. | |
In this case inspection of the callable won't help because the callback | |
takes the tuple in a single arg. It will probably be necessary for users | |
to explicitly indicate that the callback is expecting exc rather than | |
exc_info. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note that the PEP proposes it as a member, not as a function. (But we should not copy that mistake.)
I agree with all these proposals. Fixing
__exit__()
sounds like the most painful one (being a dunder).