0

I am trying to declare python variables using the function exec from within a function. For example:

def func():
    varnames = ['x', 'y', 'z']
    vals = [5,5,'abc']
    exec(varnames[0] + '=vals[0]')
    print(x)


func()

results in the error:

NameError: global name 'x' is not defined

However, it is indeed the case that 'x' is in locals()

def func():
    varnames = ['x', 'y', 'z']
    vals = [5,5,'abc']
    exec(varnames[0] + '=vals[0]')
    print(locals())


func()

results in:

{'vals': [5, 5, 'abc'], 'x': 5, 'varnames': ['x', 'y', 'z']}

showing that x is present in the local namespace. Any idea why this is happening or how I can get around it?

dylkot
  • 2,275
  • 2
  • 20
  • 24
  • 2
    Most probably you're using Python 3 where `exec` can't do such things anymore. – Ashwini Chaudhary Dec 15 '14 at 01:56
  • Yes, that is correct, I am using python 3. So it is not possible to have a string that I want to use as the name of a variable in Python 3? – dylkot Dec 15 '14 at 02:02
  • 1
    Related: [Behaviour of exec function in Python 2 and Python 3](http://stackoverflow.com/questions/15086040/behaviour-of-exec-function-in-python-2-and-python-3) – Ashwini Chaudhary Dec 15 '14 at 02:02
  • 2
    @AshwiniChaudhary has it; `LOAD_NAME` and such no longer are a thing in py3. I suppose your workaround would be to force the locals lookup: `print(locals()['x'])`. – roippi Dec 15 '14 at 02:02
  • I suppose the problem I'm having with this solution is that I would like to ultimately make the newly created variable global using the 2nd positional argument: exec(varnames[0] + '=vals[0]', globals()). However, this won't work because vals is only to be found in the local namespace. Any thoughts on how I could work around this? I should say that you've been tremendously helpful already. Thanks! – dylkot Dec 15 '14 at 02:18
  • Wow, shockingly (to me) the following works: for i in range(len(varnames)): globals()[varnames[i]] = vals[i] – dylkot Dec 15 '14 at 02:31

1 Answers1

3

You can get around this by changing your print statement in the function func() from print(x) to print(locals()['x']). Your code would now look like the following. (Tested on Python 3.3.4) Between python 2 and 3 the "exec" command changed from a statement to function which changes the scope.

def func():
    varnames = ['x','y','z']
    vals = [5,5, 'abc']
    exec(varnames[1] + '=vals[1]')
    print(locals()['y'])
Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
CMS
  • 31
  • 2