Issue 14049: execfile() fails on files that use global variables inside functions (original) (raw)

main.py below fails to execute local.py, which work ok (outputs '2') when processed directly in console.

Docs are not explaining anything. They spread fear and uncertainty around locals, but nothing is said why globals may fail. http://docs.python.org/library/functions.html#execfile

---[cut main.py]--- values = {} glavues = {} execfile('local.py', glavues, values) ---[/cut]-----------

---[cut local.py]--- x = 1 def weird(): y = x + 1 return y print weird() ---[/cut]-----------

Traceback (most recent call last): File "main.py", line 5, in execfile('local.py', glavues, values) File "local.py", line 7, in print weird() File "local.py", line 5, in weird y = x + 1 NameError: global name 'x' is not defined

Searching on 'exec NameError' shows that this issue is a duplicate of (behavior issue) #1167300 which contained an essentially identical example"

exec """
... x = 3 ... def f(): ... print x ... f() ... """ in {}, {}

#1167300 was closed as a duplicate of (behavior issue) #991196, which in turn was closed as 'won't fix' (ie, works as it must). Doc issue #4831, which resulted in some doc changes, seems related to this but is not the same. I believe this issue is a duplicate of #13557, which has a patch. I will add my proposed change there.

Anyway, my comments:

In 3.2.2, this runs

#prog='''
x = 1 def weird(): y = x + 1 return y print(weird()) #''' #exec(prog)

The same uncommented does also, as does adding ',{}' to the call. Adding ',{},{}' gives the NameError. With one named {} arg passed twice, as follows, it runs.

d = {} exec(prog, d, d)

The reasons for these results are:

  1. assignments are always to the local namespace.
  2. normally, for module code, the local and global namespaces are the same.
  3. in the example, 'x=1' is the same as "values['x']=1", while within the function, 'y=x+1' looks up x in gvalues.

This is the same explanation as given in #1167300.