1

Edit: the problem is not related to ast module.

it can be reproduced with just using exec:

y = None

exec("y = 5.0")
print(y)  # prints 5.0

vs

def foo():
    y = None

    exec("y = 5.0")
    print(y)

foo()  # prints None

Original question:

I am generating code programmatically using ast module. I have following code, that works:

import ast

num = ast.Num(n=5.)
y = None
assign = ast.Assign(targets=[ast.Name(id='y', ctx=ast.Store())], value=num)
tree = ast.Module(body=[assign], type_ignores=[])
ast.fix_missing_locations(tree)
c = compile(tree, filename="", mode="exec")
exec(c)  # replaces the value of 'y' with 5.0

print(y) # prints 5.0

However, as soon as I wrap this code in a function, it stops working:

import ast

def foo():
    num = ast.Num(n=5.)

    y = None
    assign = ast.Assign(targets=[ast.Name(id='y', ctx=ast.Store())], value=num)
    tree = ast.Module(body=[assign], type_ignores=[])
    ast.fix_missing_locations(tree)
    c = compile(tree, filename="", mode="exec")
    exec(c)

    print(y)

foo()  # prints None

This is the first time I see python code behave differently after being moved inside a function. I have checked and assignment does not put y in the module (locals) either:

print(y) # NameError: name 'y' is not defined

ikamen
  • 3,175
  • 1
  • 25
  • 47

2 Answers2

1

When in a function, you can capture the assignments into any dictionary that will function as the scope for the executed statements:

def foo():
    scope = {}
    exec("y = 5.0", scope)
    print(scope['y'])

foo()  # prints 5.0
Yodogawa Mikio
  • 413
  • 3
  • 9
  • Thanks, it works. A question remains - where did the assignment go when we left scope unspecified? it's not module globals. – ikamen Sep 11 '19 at 21:25
0

Variable Y is declared in function scope and its not available outside of it. If you want Y to be available post function call return it or use a global.

Update: See my comment in relation to exec and scopes: exec() and variable scope

Rob
  • 415
  • 4
  • 12
  • Indeed, just noticed it. Tried to execute your code locally but it fails. What python version do you use? – Rob Sep 11 '19 at 21:09
  • py 3.7 or 3.8-dev – ikamen Sep 11 '19 at 21:11
  • Answer might not been most accurate but it touches on the problem of scopes. See already given answer in https://stackoverflow.com/questions/45535284/exec-and-variable-scope – Rob Sep 11 '19 at 21:14