1

I have an auto-generated Python code snippet which I'd like to exec() from within a class instance.

A simplified snippet looks like this:

prog = """
def func1():
  func2()

def func2():
  pass

func1()
"""

class test():
    def run(self):
        exec(prog)

test().run()   # results in NameError: name 'func2' is not defined
exec(prog)     # works

While func1() can be called in both cases, func2 isn't found when exec()'ing from within the class. If I run the exec(prog) first, then even the test().run() succeeds. It seems that the previous exec call left func2 at some place in the namespace where it can later be found when called from within the class.

Is there a simple and clean way to call such a code snippet containing several functions from within a class?

SiHa
  • 7,830
  • 13
  • 34
  • 43
MasterOfGizmo
  • 23
  • 1
  • 5

3 Answers3

2

You can use exec(prog, globals()) to execute the code in the global namespace.

Gribouillis
  • 2,230
  • 1
  • 9
  • 14
  • Thanks a lot. This does exactly what i was hoping for. – MasterOfGizmo Dec 21 '16 at 08:31
  • You don' t happen to know why func1() can be called in my initial approach and why only func2 was missing? Why is only func2 affected by this limitation? – MasterOfGizmo Dec 21 '16 at 08:32
  • func1 and func2 exist in the namespace (ie dictionary) where the execution holds. In your code it is the local namespace of function `run()`. As `func1()` is called in the same namespace, it works. – Gribouillis Dec 21 '16 at 08:42
1

Not that I endorse using exec... But declare the function name global:

prog = """
global func1, func2
def func1():
  func2()

def func2():
  pass

func1()
"""
DYZ
  • 55,249
  • 10
  • 64
  • 93
  • Looks good. But i'd have to parse the incoming code, search for functions and add the global statement automatically. The exec(prog, globals()) approach runs the unmodified code. – MasterOfGizmo Dec 21 '16 at 08:29
1

It is redundant to use exec for that.

class is itself an executable statement.

omri_saadon
  • 10,193
  • 7
  • 33
  • 58