2

I have the following python2 code which gives a NameError:

def myfunc():


   myvar=50
    print myvar
    print eval('myvar')
    a = 'myvar'
    print { a:eval(a) }
    print { a:a for a in ['myvar'] }
    print { a:eval(a) for a in ['myvar'] }

myfunc()

and when I now execute this python code with python2, I get the following output:

50
50
{'myvar': 50}
{'myvar': 'myvar'}
Traceback (most recent call last):
  File "tester.py", line 13, in <module>
    myfunc()
  File "tester.py", line 11, in myfunc
    print { a:eval(a) for a in ['myvar'] }
  File "tester.py", line 11, in <dictcomp>
    print { a:eval(a) for a in ['myvar'] }
  File "<string>", line 1, in <module>
NameError: name 'myvar' is not defined

Remark: This is running on a Mac... When I run the code snippet OUTSIDE of a function it works as expected...

Alex
  • 41,580
  • 88
  • 260
  • 469
  • 1
    Your code runs fine in a script only because it's not inside a function. Move the code inside a function and call it in the main script body, and you should get the same error. – hoefling Oct 19 '18 at 12:38
  • Thanks for that observation. I updated and simplified the question... – Alex Oct 19 '18 at 13:14
  • Same behaviour in Python 3. – tobias_k Oct 19 '18 at 13:19
  • If you `print(locals())` in the dict literal and in the dict comprehension, you see that `myvar` is present in the former, but not in the latter. It _is_ present in `locals()` if you directly use it, though, e.g. in `{a: myvar for a in ...}`, but not using `eval`. No idea why that is so, though. Conversely, when the code is not in a function, `myvar` is in `globals()`, which is the same in the dict comprehension. – tobias_k Oct 19 '18 at 13:27
  • 1
    Possible duplicate of [NameError using eval inside dictionary comprehension](https://stackoverflow.com/questions/32763500/nameerror-using-eval-inside-dictionary-comprehension) – hoefling Oct 19 '18 at 13:41
  • Yes it is a duplicate! – Alex Oct 19 '18 at 14:04

1 Answers1

1

You can work around this by doing...

globs, locs = globals(), locals()
print { a:eval(a, globs, locs) for a in ['myvar'] }

An explanation can be found here: eval fails in list comprehension

Martin Stone
  • 12,682
  • 2
  • 39
  • 53
  • Ah cool, so it is a not intuitive python issue! Interesting. Thanks for the answer... – Alex Oct 19 '18 at 13:33