msg337980 - (view) |
Author: Martin Hosken (Martin Hosken) |
Date: 2019-03-15 10:44 |
The following code fails: >>> lcls = {'w': 100} >>> eval('[w for x in ("hello", "world")]', None, lcls) Traceback (most recent call last): File "", line 1, in File "", line 1, in File "", line 1, in NameError: name 'w' is not defined >>> eval('[w, w, w]', None, lcls) [100, 100, 100] whereas in python2 it succeeds >>> lcls = {'w': 100} >>> eval('[w for x in ("hello", "world")]', None, lcls) [100, 100] |
|
|
msg337981 - (view) |
Author: Emmanuel Arias (eamanu) * |
Date: 2019-03-15 12:01 |
I test it on 3.7 and 3.8 and have the same problem |
|
|
msg337984 - (view) |
Author: Emmanuel Arias (eamanu) * |
Date: 2019-03-15 12:44 |
I don't know if this a bug for py3 or py2 because the the w variable is not defined on the list comprehension context. Maybe the locals on `eval` must be create w on locals context |
|
|
msg338036 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2019-03-15 21:11 |
You example is a list comprehension, but no matter. In 3.x, the value of a comprehension is the result of calling a temporary function. Functions access globals and nonlocals but not non-global locals of surrounding contexts. Class locals are an example of the latter. >>> class C: ... w = 100 ... l = [w for x in ("hello", "world")] ... Traceback (most recent call last): File "", line 1, in File "", line 3, in C File "", line 3, in NameError: name 'w' is not defined To see this, one must make sure that the name in question is not also in globals, as it is below. >>> w = 50 >>> [w for x in ("hello", "world")] [50, 50] >>> class C: ... w = 100 ... l = [w for x in ("hello", "world")] ... >>> C.l [50, 50] # Evaluated global w, not local w. When one calls eval with separate globals and locals, one is simulating class context. There should be a FAQ entry about this. |
|
|
msg344948 - (view) |
Author: Pekka Klärck (pekka.klarck) |
Date: 2019-06-07 14:54 |
More ways to be bitten by this strange behavior: >>> d = {'a': 1, 'b': 2} >>> eval('[x[k] for k in x]', {}, {'x': d}) Traceback (most recent call last): File "", line 1, in File "", line 1, in File "", line 1, in NameError: name 'x' is not defined >>> >>> def f(): ... x = {'a': 1, 'b': 2} ... return eval('[x[k] for k in x]') ... >>> f() Traceback (most recent call last): File "", line 1, in File "", line 3, in f File "", line 1, in File "", line 1, in NameError: name 'x' is not defined In both of the above cases changing eval('[x[k] for k in x]') to eval('[v for v in x.values()]') avoids the problem. There are no problems when using [x[k] for k in x] without `eval()` either. I'd prefer this to be changed, but there should at least be a note in the documentation of `eval()` about this. |
|
|
msg344949 - (view) |
Author: Pekka Klärck (pekka.klarck) |
Date: 2019-06-07 14:56 |
I encountered this issue because Robot Framework -- a generic Python based test automation framework -- supports evaluating Python expressions and this issue was reported for us: https://github.com/robotframework/robotframework/issues/3207 |
|
|