This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author terry.reedy
Recipients benjamin.peterson, docs@python, r.david.murray, techtonik, terry.reedy
Date 2012-12-29.00:00:20
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1356739220.85.0.384771041255.issue16781@psf.upfronthosting.co.za>
In-reply-to
Content
This is at most a further doc clarification issue as the code is working as documented. In a previous issue, I added the following sentence to all current versions to try to clarify this type of behavior: " If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition." (This follows " Remember that at module level, globals and locals are the same dictionary") Let's try it:

class Dummy:
    from ctypes import wintypes
    print(wintypes.LONG)

    class LOGFONT(object):
         field = wintypes.LONG
>>>
<class 'ctypes.c_long'>
Traceback (most recent call last):
...
  File "F:\Python\mypy\tem.py", line 6, in LOGFONT
    field = wintypes.LONG
NameError: name 'wintypes' is not defined

Bingo! Anatoly's result is just as documented.

The doc later says "modifications to the default locals dictionary should not be attempted." Anatoly's result is an example of why not.

Lets distill the situation:

1. The globals dict and locals mapping passed to exec are either the same object or different objects. This relation determines the execution behavior.

2. If they are the same object, the code is executed as if at module scope. They are the same if exec is called with both defaults at module scope, where globals() is locals(), or if they are explicitly made the same ("globals = locals()", "locals = globals()", or "globals=dic, locals=dic").

3. If they are different objects, the code is executed as if embedded in a (dummy) class definition. They are different if exec is called with both defaults within a class or function scope*, where globals() is not locals(), or if explicit settings leave them different ("globals = dic" where dic is not locals(), "locals=map", where map is not globals, or "globals=dic, locals=map", where dic is not map).

I believe this nails the situation#.

* In 2.x, comprehensions do not create a function scope, but in 3.x, they do. Lambda expressions always do. This is why I did not write 'within a class or function definition', as some might not see that as including comprehensions.

# The new last sentence of the second paragraph, quoted above, contradicts the older first sentence: "In all cases, if the optional parts are omitted, the code is executed in the current scope." Before 2.2, when the 'current scope' of a function was limited to global and local namespaces, that sentence was true. Indeed, it summarized points 1,2,3 above. I believe that it is not true now, and should be revised, as nonlocal namespaces cannot be seen by exec'ed code. I believe I checked that before adding the new sentence, but I would recheck before revising. I am thinking about how to perhaps rewrite the paragraph.
History
Date User Action Args
2012-12-29 00:00:20terry.reedysetrecipients: + terry.reedy, techtonik, benjamin.peterson, r.david.murray, docs@python
2012-12-29 00:00:20terry.reedysetmessageid: <1356739220.85.0.384771041255.issue16781@psf.upfronthosting.co.za>
2012-12-29 00:00:20terry.reedylinkissue16781 messages
2012-12-29 00:00:20terry.reedycreate