-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
Python 3.13: list.remove(x) performance degradation with missing x and expensive repr(x) #116792
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
So here's my two cents.
So if your code do this is a loop and the exception is hit frequently, then maybe an explicit check is due. Making the message evaluate lazily has its own issues, for example, reference cycles. Imagine the list containing a frame object that has a reference to the exception itself. Also it definitely would make the code more complicated. However, I agree this is not an ideal behavior. Constructing the repr of the object works for most of the internal data structures, but I don't think it looks pretty when the repr of the object is huge and multiline - that might be worse than the original message. From my perspective, I think the discussion should be whether to always show the repr of the objectin the message - is it worth it to have enormous string representation in the exception message in some cases. |
Whether asking for forgiveness or asking for permission is the better approach is probably out of scope here. Using |
Currently, Python has no way to evaluate lazily an error message. I propose to just revert the change: #116956 While it's nice to have a better error message, I don't think it's worth it to make raising an exception so slower. By the way, IMO the root cause is more that repr() on a PyQt object can cause a OOM, it should not happen. |
@hroncok: Impressive bisection work, congrats! :-) |
IIUC, it means that %R is unsafe at the other place for the same use case. |
I agree. |
I investigated the root cause a bit further in the case of the PyQt build OOM issue. It seems the issue is that the
|
You may report the issue to PyQt :-) |
Issue fixed by the change commit f6cdc6b. I close the issue. |
Bug report
Bug description:
Hello. When debugging a problem in sip which hanged and caused OOM kills when building PyQt5 and PyQt6 on Python 3.13, I found the following:
217f47d is the first new commit that introduces the hangs/kills.
The commit changes the exception message in
list.remove(x)
to includerepr(x)
in it.sip has the following code: https://github.com/Python-SIP/sip/blob/6.8.3/sipbuild/generator/parser/parser_manager.py#L435-L438
klass
is a complex dataclass memberValueError
exception message is never retrievedWhen changing the code to:
The hang/kill does not happen.
Further investigating the problem, it became obvious that it is the
repr()
call that now implicitly happens when constructing theValueError
inlist.remove()
causes the hang. In fact, callingrepr(klass)
directly in theelse
branch of theif
even on Python 3.12.2 causes the hangs/kills in sip-build as well.Unfortunately, I don't have a smaller reproducer than building PyQt from sources on Python 3.13.
I don't know why repr of a dataclass eats all my RAM. Perhaps the dataclass is somehow recursive like in #116647 -- that might be a problem in dataclass repr implementation.
However, I opened this issue to report this:
Constructing the
ValueError
's exception message inlist.remove(x)
is now expensive whenrepr(x)
is expensive. Could the message be perhaps lazily evaluated to avoid callingrepr(x)
when the message will never be shown, like in the trivial try-except case?CPython versions tested on:
3.13
Operating systems tested on:
Linux
The text was updated successfully, but these errors were encountered: