Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python AST node can not be executed inside a function

could anyone give me an advice about this behaviour? The next code runs fine:

import ast


node = ast.parse('def nsd(a, b):\n    if b == 0: return a    \n    return nsd(b, a%b)\n\nprint nsd(18,15)')
obj = compile(node, filename="<ast>", mode="exec")
exec obj

But when I do the same inside a function:

import ast


def foo():
    node = ast.parse('def nsd(a, b):\n    if b == 0: return a    \n    return nsd(b, a%b)\n\nprint nsd(18,15)')
    obj = compile(node, filename="<ast>", mode="exec")
    exec obj

foo()

It raises an error:

Traceback (most recent call last):
  File "C:/Users/Vectoun/PycharmProjects/untitled3/test.py", line 9, in <module>
    foo()
  File "C:/Users/Vectoun/PycharmProjects/untitled3/test.py", line 7, in foo
    exec obj
  File "<ast>", line 5, in <module>
  File "<ast>", line 3, in nsd
NameError: global name 'nsd' is not defined

I would like to be able to run this inside a function. Does anyone know how to solve this?

like image 612
vecta Avatar asked Sep 16 '25 21:09

vecta


1 Answers

If I'm not mistaken, the issue here is that when using exec you're still bound to a scope.

So running the AST code outside of a method will define nsd as global method, while running the AST code within foo() will make nsd a member of foo's direct scope, so the invocation will fail on looking up the method.

You can fix it by first defining nsd as a global:

import ast


def foo():
    code = """global nsd
def nsd(a, b):
    if b == 0:
        return a
    return nsd(b, a%b)
print nsd(18,15)
    """
    node = ast.parse(code)
    obj = compile(node, filename="<ast>", mode="exec")
    exec obj

foo()
like image 85
noamt Avatar answered Sep 19 '25 10:09

noamt