-
-
Notifications
You must be signed in to change notification settings - Fork 31k
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
comprehensions iterating over locals()
may break under some trace funcs in 3.12
#105256
Comments
I recently discovered code of this form in
Given the inherently unstable nature of the |
My current plan to address this is to a) document it in the What's New for Python 3.12, and b) run a search over popular PyPI projects to look for comprehensions that iterate over I think longer-term the right fix for this issue is something like PEP 667, so that |
Just to add that We have fixed a bug where This problem has been there since at least 3.8(that's what I checked, I assume it would be even earlier). I strongly agree that we should do something about |
I used GitHub code search to search for the regex |
…honGH-106378) (cherry picked from commit 13aefd1) Co-authored-by: Carl Meyer <carl@oddbird.net>
It is already the case in all recent Python versions that the lazy-update behavior of the dictionary returned from
locals()
causes weird frame-introspection-sensitive semantics around lazy iteration oflocals()
. E.g. this code will work fine:But run this under a tracing function that simply accesses
frame.f_locals
:And suddenly you instead get
RuntimeError: dictionary changed size during iteration
.The reason is because accessing
frame.f_locals
triggers a lazy update of the cached locals dictionary on the frame from the fast locals array. And this is the same dictionary returned bylocals()
(it doesn't create a copy), and so the tracing function has the side effect of adding the keysk
andv
to the locals dictionary, while it is still being lazily iterated over. Without the access offrame.f_locals
, nothing triggers this locals-dict lazy update after the initial call tolocals()
, so the iteration is fine.This is a pre-existing problem with the semantics of
locals()
generally, and there are proposals to fix it, e.g. PEP 667.What is new in Python 3.12 is that PEP 709 means comprehensions can newly be exposed to this same issue. Consider this version of the above function:
Under PEP 709,
k
andv
are now part of the locals off
(albeit isolated and only existing during the execution of the comprehension), which means this version off
is now subject to the same issue as the previous for-loop version, if run under a tracing func that accessesf_locals
.Linked PRs
The text was updated successfully, but these errors were encountered: