Just adding a datapoint, searching our internal codebase at work, I only found two things that I'd consider to be uses of PyEval_GetLocals() outside of CPython itself:
https://github.com/earwig/mwparserfromhell/blob/develop/src/mwparserfromhell/parser/ctokenizer/tokenizer.c#L220 https://github.com/numba/numba/blob/master/numba/_dispatcher.cpp#L664 The bulk of uses are naturally with CPython's own ceval.c and similar. -gps On Mon, Aug 23, 2021 at 9:02 AM Guido van Rossum <gu...@python.org> wrote: > On Mon, Aug 23, 2021 at 8:46 AM Mark Shannon <m...@hotpy.org> wrote: > >> Hi Guido, >> >> On 23/08/2021 3:53 pm, Guido van Rossum wrote: >> > On Mon, Aug 23, 2021 at 4:38 AM Mark Shannon <m...@hotpy.org >> > <mailto:m...@hotpy.org>> wrote: >> > >> > Hi Nick, >> > >> > On 22/08/2021 4:51 am, Nick Coghlan wrote: >> > >> > > If Mark's claim that PyEval_GetLocals() could not be fixed was >> > true then >> > > I would be more sympathetic to his proposal, but I know it isn't >> > true, >> > > because it still works fine in the PEP 558 implementation (it >> even >> > > immediately sees changes made via proxies, and proxies see >> > changes to >> > > extra variables). The only truly unfixable public API is >> > > PyFrame_LocalsToFast(). >> > >> > You are making claims that seem inconsistent with each other. >> > Namely, you are claiming that: >> > >> > 1. That the result of locals() is ephemeral. >> > 2. That PyEval_GetLocals() returns a borrowed reference. >> > >> > This seems impossible, as you can't return a borrowed reference to >> > an emphemeral object. That's just a pointer to freed memory. >> > >> > Do `locals()` and `PyEval_GetLocals()` behave differently? >> > >> > >> > That is my understanding, yes. in PEP 558 locals() returns a snapshot >> > dict, the Python-level f_locals property returns a fresh proxy that has >> > no state except a pointer to the frame, and PyEval_GetLocals() returns >> a >> > borrowed reference to the dict that's stored on the frame's C-level >> > f_locals attribute >> >> Can we avoid describing the C structs in any of these PEPs? >> >> It confuses readers having Python attributes and "C-level attributes" >> (C struct fields?). >> It also restricts the implementation unnecessarily. >> >> (E.g. the PyFrameObject doesn't have a `f_locals` field in 3.11: >> >> https://github.com/python/cpython/blob/main/Include/cpython/frameobject.h#L7 >> ) >> > > I'd be happy to. Nick's PEP still references it (and indeed it is very > confusing) and I took it from him. And honestly it would be nice to have a > specific short name for it, rather than circumscribing it with "an internal > dynamic snapshot stored on the frame object " :-) > > >> > >> > (In my "crazy" proposal all that is the same.) >> >> > >> > Is the result of `PyEval_GetLocals()` cached, but `locals()` not? >> > >> > >> > I wouldn't call it a cache -- deleting it would affect the semantics, >> > not just the performance. But yes, it returns a reference to an object >> > that is owned by the frame, just as it does in 3.10 and before. >> > >> > If that were the case, then it is a bit confusing, but could work. >> > >> > >> > Yes, see my "crazy" proposal. >> > >> > Would PyEval_GetLocals() be defined as something like this? >> > >> > (add _locals_cache attribute to the frame which is initialized to >> NULL). >> > >> > def PyEval_GetLocals(): >> > frame._locals_cache attribute = locals() >> > return borrow(frame._locals_cache attribute) >> > >> > >> > Nah, the dict returned by PyEval_GetLocals() is stored in the frame's >> > C-level f_locals attribute, which is consulted by the Python-level >> > f_locals proxy -- primarily to store "extra" variables, but IIUC in >> > Nick's latest version it is also still used to cache by that proxy. >> > Nick's locals() just returns dict(sys._getframe().f_locals). >> >> The "extra" variables must be distinct from the result of locals() as >> that includes both extras and "proper" variables. >> If we want to cache the locals(), it needs to be distinct from the extra >> variables. >> > > I don't care that much about caching locals(), but it seems we're bound to > cache any non-NULL result from PyEval_GetLocals(), since it returns a > borrowed reference. So they may be different things, with different > semantics, if we don't cache locals(). > > >> A debugger setting extra variables in a function that that is also >> accessed by a C call to PyEval_GetLocals() is going to be incredibly >> rare. Let's not worry about efficiency here. >> > > Agreed. > > > >> > None of this is clear (at least not to me) from PEP 558. >> > >> > >> > One problem with PEP 558 is that it's got too many words, and it's >> > lacking a section that crisply describes the semantics of the proposed >> > implementation. I've suggested to Nick that he add a section with >> > pseudo-code for the implementation, like you did in yours. >> > >> > (PS, did you read my PS about what locals() should do in class scope >> > when __prepare__ returns a non-dict?) >> >> Yes, but no harm in a reminder :) >> I'll update my PEP to fix the semantics of locals(). >> > > I'm in suspense as to what semantics you chose. :-) > > PS. Another point where you seem to have missed some detail is in the > mapping from (proper) variable names to "frame locals" -- you use > co_varnames, but that (currently, at least) doesn't include cells. > > -- > --Guido van Rossum (python.org/~guido) > *Pronouns: he/him **(why is my pronoun here?)* > <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/> > _______________________________________________ > 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/AK23IEZKC3DQBPYBTKA7NHDPUNSV55WZ/ > Code of Conduct: http://python.org/psf/codeofconduct/ >
_______________________________________________ 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/37SMUITK5QIWQZNUCTCWZBNUP36RDHOM/ Code of Conduct: http://python.org/psf/codeofconduct/