You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[C API] Enhance PyErr_WriteUnraisable() API to pass an error message #108082
This is a minor feature, which does not need previous discussion elsewhere
Links to previous discussion of this feature:
No response
Proposal:
I added a private _PyErr_WriteUnraisableMsg() API but it cannot be used in third party code, nor in stdlib extensions which try to avoid private/internal functions (like sqlite3). Moreover, _PyErr_WriteUnraisableMsg() API doesn't allow to fully customize the error message.
The limitation of _PyErr_WriteUnraisableMsg() affected PR #106674 which has to add ; consider using ... in the error message which is not great.
_PyErr_WriteUnraisableMsg(
"in PyMapping_HasKeyString(); consider using ""PyMapping_GetOptionalItemString() or PyMapping_GetItemString()",
NULL);
@serhiy-storchaka suggested to add an API which allows string formatting, similar to PyErr_Format().
_PyErr_WriteUnraisableMsg() was added in issue #81010.
By the way, we should go through all calls to PyErr_WriteUnraisable() and add more context to more these logs easier to get for developers: give more context about what the issue is, how to fix it, where it occurred, etc.
With PyErr_WriteUnraisable(obj) equal to PyErr_FormatUnraisable(obj, "Exception ignored in: %R", obj) or special case PyErr_FormatUnraisable(obj, NULL).
Or we always set UnraisableHookArgs.object to None if use PyErr_FormatUnraisable(), then we can make the use simpler. Then custom message and object will be mutually exclusive, but seems that currently most of cases with custom message pass NULL as object.
Or we can keep PyErr_FormatUnraisable() simpler and add a separate function PyErr_FormatUnraisableObject() which allows to specify both custom message and object.
They can be replaced with PyErr_FormatUnraisable(), but then object will be None. Or we can add new function specially for these cases, which passes both object and a format with arguments for a warning message. I do not know how important to have object.
They can be replaced with PyErr_FormatUnraisable(), but then object will be None. Or we can add new function specially for these cases, which passes both object and a format with arguments for a warning message. I do not know how important to have object.
As the author of _PyErr_WriteUnraisableMsg(), I suggest to remove _PyErr_WriteUnraisableMsg() and replace all _PyErr_WriteUnraisableMsg() usage with PyErr_FormatUnraisable().
My intent for passing object to the hook was to delegate the formatting to give the hook the opportunity to catch exception on formatting the object, and maybe use tracemalloc to see where the object was allocated, etc.
But I don't think that these features are really useful and we should just skip/remove object, and just pass an error message to the hook.
Activity
serhiy-storchaka commentedon Aug 17, 2023
I already started to work on this, but was not sure about API, so left it to your return.
I initially was going to add simple function:
With special case
PyErr_FormatUnraisable(NULL, obj)equal toPyErr_WriteUnraisable(obj).But it now creates the
UnraisableHookArgsobject which has fieldobject. So we need more complex API:With
PyErr_WriteUnraisable(obj)equal toPyErr_FormatUnraisable(obj, "Exception ignored in: %R", obj)or special casePyErr_FormatUnraisable(obj, NULL).Or we always set
UnraisableHookArgs.objecttoNoneif usePyErr_FormatUnraisable(), then we can make the use simpler. Then custom message andobjectwill be mutually exclusive, but seems that currently most of cases with custom message pass NULL as object.Or we can keep
PyErr_FormatUnraisable()simpler and add a separate functionPyErr_FormatUnraisableObject()which allows to specify both custom message and object.vstinner commentedon Sep 4, 2023
I wrote PR #108863 to remove the private _PyErr_WriteUnraisableMsg() function from the public C API.
pythongh-108082: Add PyErr_FormatUnraisable() function
pythongh-108082: C API: Add tests for PyErr_WriteUnraisable()
gh-108082: C API: Add tests for PyErr_WriteUnraisable() (GH-111455)
pythongh-108082: C API: Add tests for PyErr_WriteUnraisable() (python…
[3.12] gh-108082: C API: Add tests for PyErr_WriteUnraisable() (GH-11…
gh-108082: Add PyErr_FormatUnraisable() function (GH-111086)
pythongh-108082: Use PyErr_FormatUnraisable()
gh-108082: Use PyErr_FormatUnraisable() (GH-111580)
serhiy-storchaka commentedon Nov 2, 2023
Few calls of
_PyErr_WriteUnraisableMsgare left which pass both message and non-NULL object.They can be replaced with
PyErr_FormatUnraisable(), but thenobjectwill be None. Or we can add new function specially for these cases, which passes bothobjectand a format with arguments for a warning message. I do not know how important to haveobject.pythongh-108082: Remove _PyErr_WriteUnraisableMsg()
vstinner commentedon Nov 2, 2023
As the author of _PyErr_WriteUnraisableMsg(), I suggest to remove _PyErr_WriteUnraisableMsg() and replace all _PyErr_WriteUnraisableMsg() usage with PyErr_FormatUnraisable().
My intent for passing object to the hook was to delegate the formatting to give the hook the opportunity to catch exception on formatting the object, and maybe use tracemalloc to see where the object was allocated, etc.
But I don't think that these features are really useful and we should just skip/remove object, and just pass an error message to the hook.
2 remaining items
pythongh-108082: C API: Add tests for PyErr_WriteUnraisable() (python…
pythongh-108082: Add PyErr_FormatUnraisable() function (pythonGH-111086)
pythongh-108082: Use PyErr_FormatUnraisable() (pythonGH-111580)
pythongh-108082: Remove _PyErr_WriteUnraisableMsg() (pythonGH-111643)
serhiy-storchaka commentedon Nov 3, 2023
Now we can replace more
PyErr_Clear()with informativePyErr_FormatUnraisable().pythongh-108082: C API: Add tests for PyErr_WriteUnraisable() (python…
pythongh-108082: Add PyErr_FormatUnraisable() function (pythonGH-111086)
pythongh-108082: Use PyErr_FormatUnraisable() (pythonGH-111580)
pythongh-108082: Remove _PyErr_WriteUnraisableMsg() (pythonGH-111643)
pythongh-108082: C API: Add tests for PyErr_WriteUnraisable() (python…
pythongh-108082: Add PyErr_FormatUnraisable() function (pythonGH-111086)
pythongh-108082: Use PyErr_FormatUnraisable() (pythonGH-111580)
pythongh-108082: Remove _PyErr_WriteUnraisableMsg() (pythonGH-111643)
test: Close file handles in contrib tests for Python 3.14