I apologize. This does indeed not work. What does work, however, is setting a variable from a tracing function. There is magic in the tracing machinery that writes back the variables to the frame when the tracing function returns. This causes the bug referenced as [1] in both PEPs, and both propose to fix the bug by not writing things back that way, instead writing back whenever a key in the proxy is set. The discussion is about subtler differences between the proposals.
—Guido On Mon, Aug 23, 2021 at 22:19 Steven D'Aprano <st...@pearwood.info> wrote: > On Sat, Aug 21, 2021 at 05:46:52PM -0700, Guido van Rossum wrote: > > Hopefully anyone is still reading python-dev. > > I am :-) > > [...] > > Everything here is about locals() and f_locals in *function scope*. (I > use > > f_locals to refer to the f_locals field of frame objects as seen from > > Python code.) And in particular, it is about what I'll call "extra > > variables": the current CPython feature that you can add *new* variables > to > > f_locals that don't exist in the frame, for example: > > > > def foo(): > > x = 1 > > locals()["y"] = 2 # or sys._getframe()["y"] = 2 > > I'm confused. I don't think it currently works, at least not in the > sense that I understand "works" to mean. Sure, you can add a new key to > the dict, but that doesn't add a new local variable: > > > >>> def spam(): > ... if False: y = 0 # Fool the compiler into treating y as a > local. > ... x = 0 > ... locals()['y'] = 1 > ... print(sys._getframe().f_locals) > ... print(y) > ... > >>> spam() > {'x': 0} > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "<stdin>", line 6, in spam > UnboundLocalError: local variable 'y' referenced before assignment > > > Am I missing something? The above is in 3.9, has something changed in > 3.10 or am I just misunderstanding what you mean by "works"? > > Using f_locals instead of locals() doesn't change the UnboundLocalError > in my testing. > > If you are not referring to new local variables, then I don't understand > what these "extra variables" are or where they live in the current > implementation. > > A recent thread on Discuss is maybe relevant: > > > https://discuss.python.org/t/how-can-i-use-exec-in-functions-in-python3-6-similar-to-python2-7/10191 > > Would either of these two proposals re-enable exec to work inside > functions as it used to? > > I think Nick's PEP 558 does not, it wants to make it explicit that > changes to locals will not be reflected in the local variables. Although > Nick does refer to a "write back" strategy that apparently works *now*. > That suggests: > > - there currently is a trick to writing new local variables in the > function namespace; > > - and Nick's PEP will break it. > > Am I correct? > > Mark's PEP 667 says "However f.f_locals == f.f_locals will be True, and > all changes to the underlying variables, by any means, will be always be > visible" so I think that means it will allow exec to work as in > Python2.x, at least if you pass sys._getframe().f_locals to exec instead > of locals(). > > Perhaps we need an informational PEP to explain how local variables > inside functions work now :-) > > > > -- > Steve > _______________________________________________ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@python.org > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/python-dev@python.org/message/CREZXKZWVSICQY4WHKUPXGJU67UUPQZ2/ > Code of Conduct: http://python.org/psf/codeofconduct/ > -- --Guido (mobile)
_______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/WHK32PFNLULIRQMHPFIC3SETT2O6PMKV/ Code of Conduct: http://python.org/psf/codeofconduct/