3

Looking for good explanation of why this code raises SyntaxError.

def echo(x):
    return x

def foo(s):
    d = {}
    exec(s, {}, d)
    return dict((x,y) for x,y in d.items())

def bar(s):
    d = {}
    exec(s, {}, d)
    return dict((x, echo(y)) for x,y in d.items()) # comment this to compile

s = 'a=1'
foo(s)

  File "test.py", line 11
    exec(s, {}, d)
SyntaxError: unqualified exec is not allowed in function 'bar' it contains a
             nested function with free variables
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
Shekhar
  • 7,095
  • 4
  • 40
  • 45
  • 6
    What on earth is this supposed to do? – Daniel Roseman Feb 08 '12 at 14:35
  • 3
    @DanielRoseman: The actual question seems to be: Why is `foo()` valid Python while `bar()` isn't? A very valid question in my opinion, though it should be stated a bit clearer. – Sven Marnach Feb 08 '12 at 14:40
  • 1
    @DanielRoseman :D This code is just for explanation. Real code is much more acceptable version. I was just looking for exec's explanation. – Shekhar Feb 08 '12 at 14:42
  • 2
    You should really quote the error you are getting, since that is what you are asking about. If everybody has to run the code themselves first to see what exactly you are talking about, then your question is very flawed. – sth Feb 08 '12 at 14:43
  • @SvenMarnach sorry, was commenting before the error got edited into the question! – snim2 Feb 08 '12 at 14:49
  • @snim2 yes it's close to duplicate but question is specific and SvenMarnach's Answer is useful. I guess this can stay. – Shekhar Feb 08 '12 at 15:03

2 Answers2

7

In Python 2.x, exec statements may not appear inside functions that have local "functions" with free variables. A generator expression implicitly defines some kind of "function" (or more precisely, a code object) for the code that should be executed in every iteration. In foo(), this code only contains references to x and y, which are local names inside the generator expression. In bar(), the code also contains a reference to the free variable echo, which disqualifies bar() for the use of exec.

Also note that your exec statements are probably supposed to read

exec s in {}, d

which would turn them into qualified exec statements, making the code valid.

Note that your code would work in Python 3.x. exec() has been turned into a function and can no longer modify the local variables of the enclosing function, thus making the above restriction on the usage of exec unnecessary.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
3

You probably try to write python 2.x code using a python 3.x manual. With Python 3.2 I don't get this error and in Python 2.7 the exec syntax is quite different.

wRAR
  • 25,009
  • 4
  • 84
  • 97