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 Kevin Shweh, gvanrossum, lys.nikolaou, pablogsal, terry.reedy
Date 2020-10-31.00:37:01
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1604104621.85.0.491018690771.issue42190@roundup.psfhosted.org>
In-reply-to
Content
exec with different global and local dicts is most like executing code in a class definition, where locals is different from globals.  But mimicking your exec with an actual class statement does not produce the same result.

>>> gdict = {}
>>> class C:
	x = 1
	def f(): global x
	
>>> gdict
{}
>>> C.x
1

# To continue, I reproduced the behavior in 3.10.
>>> ldict = {}
>>> exec('''
x = 1
def f(): global x''', gdict, ldict)
>>> 'x' in gdict
True

# And that putting x in gdict required the global declaration.
>>> gdict = {}
>>> exec('''
x = 1
def f(): pass''', gdict, ldict)

>>> 'x' in gdict
False
>>> 'x' in ldict
True

This seems like a bug to me too.  The change is in the bytecode, not the subsequent execution thereof.

>>> dis.dis('x = 1')
  1           0 LOAD_CONST               0 (1)
              2 STORE_NAME               0 (x)
              ...

# Ditto if add '\ndef f(): pass', but here is the test case.
>>> dis.dis('x = 1\ndef f(): global x')
  1           0 LOAD_CONST               0 (1)
              2 STORE_GLOBAL             0 (x)
              ...

# Same result for 'global x; x = 1', but 'x = 1; global x' raises
SyntaxError: name 'x' is assigned to before global declaration


The change is inconsequential when locals is globals, but not when not.
History
Date User Action Args
2020-10-31 00:37:01terry.reedysetrecipients: + terry.reedy, gvanrossum, Kevin Shweh, lys.nikolaou, pablogsal
2020-10-31 00:37:01terry.reedysetmessageid: <1604104621.85.0.491018690771.issue42190@roundup.psfhosted.org>
2020-10-31 00:37:01terry.reedylinkissue42190 messages
2020-10-31 00:37:01terry.reedycreate