Issue 36300: eval of comprehension cannot access local variables (original) (raw)

Created on 2019-03-15 10:44 by Martin Hosken, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (6)
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) * (Python committer) 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
History
Date User Action Args
2022-04-11 14:59:12 admin set github: 80481
2019-06-07 14:56:27 pekka.klarck set messages: +
2019-06-07 14:54:57 pekka.klarck set nosy: + pekka.klarckmessages: +
2019-03-15 21:11:09 terry.reedy set status: open -> closedtitle: eval of generator expressions cannot access local variables -> eval of comprehension cannot access local variablesnosy: + terry.reedyversions: - Python 2.7, Python 3.6messages: + resolution: not a bugstage: resolved
2019-03-15 12:44:49 eamanu set type: behaviormessages: + versions: + Python 2.7
2019-03-15 12:01:53 eamanu set nosy: + eamanumessages: + versions: + Python 3.7, Python 3.8
2019-03-15 10:45:03 Martin Hosken set versions: + Python 3.6
2019-03-15 10:44:12 Martin Hosken create