Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32.4k
DOCS: Suggest always calling exec with a globals argument and no locals argument#119235
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
…ls argumentMany users think they want a locals argument for various reasons but they do notunderstand that it makes code be treated as a class definition. They do not wanttheir code treated as a class definition and get surprised. The reason notto pass locals specifically is that the following code raises a `NameError`:```pyexec("""def f(): print("hi")f()def g(): f()g()""", {}, {})```The reason not to leave out globals is as follows:```pydef t(): exec("""def f(): print("hi")f()def g(): f()g() """)```
same overall meaning.
…ls argument (pythonGH-119235)Many users think they want a locals argument for various reasons but they do notunderstand that it makes code be treated as a class definition. They do not wanttheir code treated as a class definition and get surprised. The reason notto pass locals specifically is that the following code raises a `NameError`:```pyexec("""def f(): print("hi")f()def g(): f()g()""", {}, {})```The reason not to leave out globals is as follows:```pydef t(): exec("""def f(): print("hi")f()def g(): f()g() """)```(cherry picked from commit7e1a130)Co-authored-by: Hood Chatham <roberthoodchatham@gmail.com>
…ls argument (pythonGH-119235)Many users think they want a locals argument for various reasons but they do notunderstand that it makes code be treated as a class definition. They do not wanttheir code treated as a class definition and get surprised. The reason notto pass locals specifically is that the following code raises a `NameError`:```pyexec("""def f(): print("hi")f()def g(): f()g()""", {}, {})```The reason not to leave out globals is as follows:```pydef t(): exec("""def f(): print("hi")f()def g(): f()g() """)```(cherry picked from commit7e1a130)Co-authored-by: Hood Chatham <roberthoodchatham@gmail.com>
GH-119239 is a backport of this pull request to the3.13 branch. |
GH-119240 is a backport of this pull request to the3.12 branch. |
…no locals argument (GH-119235) (#119240)DOCS: Suggest always calling exec with a globals argument and no locals argument (GH-119235)Many users think they want a locals argument for various reasons but they do notunderstand that it makes code be treated as a class definition. They do not wanttheir code treated as a class definition and get surprised. The reason notto pass locals specifically is that the following code raises a `NameError`:```pyexec("""def f(): print("hi")f()def g(): f()g()""", {}, {})```The reason not to leave out globals is as follows:```pydef t(): exec("""def f(): print("hi")f()def g(): f()g() """)```(cherry picked from commit7e1a130)Co-authored-by: Hood Chatham <roberthoodchatham@gmail.com>
…no locals argument (GH-119235) (#119239)DOCS: Suggest always calling exec with a globals argument and no locals argument (GH-119235)Many users think they want a locals argument for various reasons but they do notunderstand that it makes code be treated as a class definition. They do not wanttheir code treated as a class definition and get surprised. The reason notto pass locals specifically is that the following code raises a `NameError`:```pyexec("""def f(): print("hi")f()def g(): f()g()""", {}, {})```The reason not to leave out globals is as follows:```pydef t(): exec("""def f(): print("hi")f()def g(): f()g() """)```(cherry picked from commit7e1a130)Co-authored-by: Hood Chatham <roberthoodchatham@gmail.com>
ncoghlan commentedMay 21, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Just a heads up that I included a rewording of this note in the PEP 667 docs PR at#119201 (seehttps://github.com/python/cpython/pull/119201/files#r1607516295 ) after hitting a conflict between this change and that one. Users pass a separate
That PR will only get backported as far as 3.13 (since the rest of the PR is specific to a 3.13 change). I'm not sure it's worth worrying about changing the note in 3.12, though. |
Thanks@ncoghlan! I wanted to keep to as few words as possible here so that the PR wouldn't get bogged down in discussion. I am always concerned that each added word makes it more likely that the PR leads to an endless discussion, I run out of energy, and it goes stale. |
Interesting! |
I actually need to revisit that updated note, as I was reminded today that
(and there are unfortunately genuine performance reasons for that restriction, so relaxing it would be easier said than done) |
When updating the new exec note added inpythongh-119235 as part of thePEP 667 general docs PR, I suggested a workaround that isn't valid.Since it's far from the first time I've considered that workaround,and the fact it doesn't work has surprised me every time, amend thenew note to explicitly state that dict merging is the only option.
When updating the new exec note added ingh-119235 as part of thePEP 667 general docs PR, I suggested a workaround that isn't valid.The first half of the note is still reasonable, so just omit the invalid text.
When updating the new exec note added inpythongh-119235 as part of thePEP 667 general docs PR, I suggested a workaround that isn't valid.The first half of the note is still reasonable, so just omit the invalid text.(cherry picked from commit31d61a7)Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com>
I think what people may want when they pass locals is for |
Thanks Alyssa, I wasn't totally happy with the wording in this PR but felt it started to shift us towards the right thing to express. I like your wording better. On of my key issues is that long existing "the code will be executed as if it were embedded in a class definition" wording (from before this PR) is the kind of thing that most docs readers are not likely to understand as it's "weird" but most people need never understand it. Your new text expands upon that in an accessible descriptive manner. |
CNSeniorious000 commentedJun 3, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I think the best practise to implement layered context is to use Let's say you have 2 maps, a Mapping But! eval's fromcollectionsimportChainMapclassChainMap(ChainMap,dict):pass Reproduction:>>>fromcollectionsimportChainMap>>>g,l= {"a":2}, {}>>>source="""... def f():... return g() + 1...... def g():... return a...... a = f()... """>>>exec(source,ChainMap(l,g))Traceback (mostrecentcalllast):File"<console>",line1,in<module>TypeError:globalsmustbearealdict;tryeval(expr, {},mapping)>>>classChainMap(ChainMap,dict):...pass...>>>exec(source,ChainMap(l,g))>>>g{'a':2}>>>l{'f':<functionfat0xa04368>,'g':<functiongat0x12654d0>,'a':3} I think its a common use case to avoid pollution on the global namespace when using |
…ls argument (pythonGH-119235)Many users think they want a locals argument for various reasons but they do notunderstand that it makes code be treated as a class definition. They do not wanttheir code treated as a class definition and get surprised. The reason notto pass locals specifically is that the following code raises a `NameError`:```pyexec("""def f(): print("hi")f()def g(): f()g()""", {}, {})```The reason not to leave out globals is as follows:```pydef t(): exec("""def f(): print("hi")f()def g(): f()g() """)```
When updating the new exec note added inpythongh-119235 as part of thePEP 667 general docs PR, I suggested a workaround that isn't valid.The first half of the note is still reasonable, so just omit the invalid text.
Uh oh!
There was an error while loading.Please reload this page.
Many users think they want a locals argument for various reasons but they do not understand that it makes code be treated as a class definition. They do not want their code treated as a class definition and get surprised. The reason not to pass locals specifically is that the following code raises a
NameError
:The reason not to leave out globals is as follows:
📚 Documentation preview 📚:https://cpython-previews--119235.org.readthedocs.build/