Reputation: 3493
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
Upvotes: 1
Views: 214
Reputation: 423
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
Upvotes: 1
Reputation: 481
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
Upvotes: 0