Search code examples
pythondynamicexec

Python variable scope for exec?


Below are 2 code snippets.

I would like to duplicate the effect of f1, where an outer variable x is modified by an inner function g.

However, instead of defining an inner function g, g is obtained by executing/interpreting a string.

code:

def f1():
  x = []
  def g():
    x.append(1)
  g() 
  print x


def f2():
  x = []
  strr = "def g():\n  x.append(1)\n"
  exec(strr)
  locals()["g"]()
  print x

In f1 I get [1] as the print out, but in f2 I get x undefined error. I would like to know how I can make the variable x accessible in the string-defined function g.

follow up:

What would happen if I want to apply a decorator to g? say I have a "timeout" decorator that fails a function if it takes too long to run:

def f1():
  x = []
  @timeout(1)
  def g():
    x.append(1)
  g() 
  print x

edit: I managed to solve it as follows, since timeout is not defined locally, I have to move the definition of timeout from global to local, the proceed as usual.

def f2():
  x = []
  strr = "@timeout(1)\ndef g():\n  x.append(1)\n"
  locals()['timeout'] = globals()['timeout']
  exec strr in locals()
  locals()["g"]()
  print x

Solution

  • You need to add the name space for exec. Use the local name space (exec strr in locals()) and it works:

    def f2():
        x = []
        strr = "def g():\n  x.append(1)\n"
        exec strr in locals()
        locals()["g"]()
        print x
    
    >>> f2()
    [1]