[Python-Dev] bpo-36829: Add sys.unraisablehook() (original) (raw)
Nathaniel Smith njs at pobox.com
Thu May 16 21:32:39 EDT 2019
- Previous message (by thread): [Python-Dev] bpo-36829: Add sys.unraisablehook()
- Next message (by thread): [Python-Dev] bpo-9584: Added brace expressions to the glob and fnmatch.
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Thu, May 16, 2019 at 1:23 PM Victor Stinner <vstinner at redhat.com> wrote:
Le jeu. 16 mai 2019 à 20:58, Petr Viktorin <encukou at gmail.com> a écrit : > I always thought the classic (exctype, excvalue, exctb) triple is a > holdover from older Python versions, and all the information is now in > the exception instance. > Is the triple ever different from (type(exc), exc, exc.traceback)? > (possibly with a getattr for traceback) I added assertions in PyErrWriteTraceback(): assert(PyTYPE(v) == t); assert(PyExceptionGetTraceback(v) == tb); "PyTYPE(v) == t" fails in testexceptions.testmemoryerrorinPyErrPrintEx() for example. PyErrNoMemory() calls PyErrSetNone(PyExcMemoryError), it sets tstate->curexctype to PyExcMemoryError, but tstate->curexcvalue is set to NULLL.
This makes some sense – if you can't allocate memory, then better not allocate an exception instance to report that! So this is legitimately a special case.
But... it looks like everywhere else, the way we handle this when transitioning into Python code is to create an instance. For example, that test does 'except MemoryError as e', so an instance does need to be created then. The comments suggest that there's some trick where we have pre-allocated MemoryError() instances? But either way, if we can afford to call a Python hook (which requires at least allocating a frame!), then we can probably also afford to materialize the MemoryError instance. So I feel like maybe we shouldn't be passing None to the unraisable hook, even if PyErr_NoMemory() did initially set that?
Also, in practice, the only time I've ever seen MemoryError is from attempting to do a single massively-huge allocation. It's never meant that regular allocation of small objects will fail.
"PyExceptionGetTraceback(v) == tb" fails in testexceptions.testunraisable() for example: "PyTraceBackHere(f);" in the "error:" label of ceval.c creates a traceback object and sets it to tstate->curexectraceback, but it doesn't set the traceback attribute of the current exception.
Isn't this just a bug that should be fixed?
> Should new APIs use it?
I tried to add a "PyErrNormalizeException(&t, &v, &tb);" call in PyErrWriteUnraisable(): it creates an exception object (excvalue) for the PyErrNoMemory() case, but it still doesn't set the traceback attribute of the exception for the PyTraceBackHere() case. It seems like PyErrWriteUnraisable() cannot avoid having 3 variables (exctype, excvalue, exctb), since they are not consistent as you may expect.
I'm actually fine with it having three arguments -- even if it's technically unnecessary, it's currently 100% consistent across these low-level APIs, and it doesn't hurt anything, so we might as well stick with it for consistency.
-n
-- Nathaniel J. Smith -- https://vorpus.org
- Previous message (by thread): [Python-Dev] bpo-36829: Add sys.unraisablehook()
- Next message (by thread): [Python-Dev] bpo-9584: Added brace expressions to the glob and fnmatch.
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]