Python Forum
namespaces in comprehension in exec() - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: namespaces in comprehension in exec() (/thread-2588.html)



namespaces in comprehension in exec() - Skaperen - Mar-27-2017

first, here is the (nearly) minimalized code by itself:

s="foo = 1\nfor n in range(10):\n    x = [n**m for m in range(9)]\nbar = 0"
g={}
l={}
print(s)
exec(s,g,l)
print(repr(l))
secondly here is the output i get:
Output:
lt1/forums /home/forums 6> py3 --version Python 3.5.2 lt1/forums /home/forums 7> cat try.py s="foo = 1\nfor n in range(10):\n    x = [n**m for m in range(9)]\nbar = 0" g={} l={} print(s) exec(s,g,l) print(repr(l)) lt1/forums /home/forums 8> py3 try.py foo = 1 for n in range(10):     x = [n**m for m in range(9)] bar = 0 Traceback (most recent call last):   File "try.py", line 5, in <module>     exec(s,g,l)   File "<string>", line 3, in <module>   File "<string>", line 3, in <listcomp> NameError: name 'n' is not defined lt1/forums /home/forums 9>
it looks like that while executing under exec(), the local namespace is not used in a comprehension.  it works as expected under python2:
Output:
lt1/forums /home/forums 10> py2 --version Python 2.7.12 lt1/forums /home/forums 11> cat try.py s="foo = 1\nfor n in range(10):\n    x = [n**m for m in range(9)]\nbar = 0" g={ l={} print(s) exec(s,g,l) print(repr(l)) lt1/forums /home/forums 12> py2 try.py foo = 1 for n in range(10):     x = [n**m for m in range(9)] bar = 0 {'x': [1, 9, 81, 729, 6561, 59049, 531441, 4782969, 43046721], 'foo': 1, 'm': 8, 'bar': 0, 'n': 9} lt1/forums /home/forums 13>
i did not get that empty line that appears to be output by command 10.  that's a bug in MyBB somewhere.  i take it out and posting puts it back in (could be a bug in the client side code).  now it moved it to command 11. got it out this time. but it remove the closing brace of the empty dict assignment to g.


RE: namespaces in comprehension in exec() - zivoni - Mar-27-2017

List comprehensions were changed in python 3 (to prevent leaking of "inside" variables) and have proper scope. And thats reason why inside of list comprehension defined in the class you cant see class variables - its explained in Accessing class variables from a list comprehension in the class definition

And as its explicitily stated in exec docs:
Quote:If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.

So use only globals directory (why you need to pass locals anyway?) or rewrite your list comprehension as a for loop.


RE: namespaces in comprehension in exec() - Skaperen - Mar-27-2017

(Mar-27-2017, 08:40 AM)zivoni Wrote: why you need to pass locals anyway?

i am making "python format" config files.  that means lots of simple coding will be used that just does put things in the local namespace.

account = "080643210675"
vin = "1HGBH41JXMN109186"
phone = "+18009004321"
it doesn't have to be locals.  it just has to be somewhere.  if nothing else is added to to the space then there is the option to extract "misspelled" config options.  but the global space gets stuff added so it is to be avoid if that option is to be used.  my pyconf() function was intended to return a dictionary of what the config file set.  so, the issue of how comprehensions are used is going to be used will be the same in a python format config file as in regular code.  no big deal.  however people deal with it in regular code, just do the same in a python format config file.  use of comprehensions in config files is expected to be much less frequent in config files than in regular code.  and they are rare in regular code.  it was just a happen chance that i used one.  i did not know of the namespace isolation thing.  now i do.


RE: namespaces in comprehension in exec() - zivoni - Mar-27-2017

(Mar-27-2017, 10:11 AM)Skaperen Wrote: it doesn't have to be locals.  it just has to be somewhere.  if nothing else is added to to the space then there is the option to extract "misspelled" config options.  but the global space gets stuff added so it is to be avoid if that option is to be used.  my pyconf() function was intended to return a dictionary of what the config file set.  so, the issue of how comprehensions are used is going to be used will be the same in a python format config file as in regular code.  no big deal.

Isolation of executed code can be achieved just with globals parameter (globals parameter has nothing common with global scope (globals()) from where you use exec). And with regular import comprehensions would work, problem is with locals parameter enforcing "class definition execution".

>>> s = "boo=1"
>>> config = {}
>>> exec(s, config)
>>> boo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'boo' is not defined
>>> config['boo']
1



RE: namespaces in comprehension in exec() - Skaperen - Mar-28-2017

(Mar-27-2017, 12:22 PM)zivoni Wrote:
(Mar-27-2017, 10:11 AM)Skaperen Wrote: it doesn't have to be locals.  it just has to be somewhere.  if nothing else is added to to the space then there is the option to extract "misspelled" config options.  but the global space gets stuff added so it is to be avoid if that option is to be used.  my pyconf() function was intended to return a dictionary of what the config file set.  so, the issue of how comprehensions are used is going to be used will be the same in a python format config file as in regular code.  no big deal.

Isolation of executed code can be achieved just with globals parameter (globals parameter has nothing common with global scope (globals()) from where you use exec). And with regular import comprehensions would work, problem is with locals parameter enforcing "class definition execution".

>>> s = "boo=1"
>>> config = {}
>>> exec(s, config)
>>> boo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'boo' is not defined
>>> config['boo']
1

why is this so important?