Alex Kleider wrote: > I'm puzzled by the following behaviour: > > The following works as I expect: > > alex@x301:~/Python$ python3 > Python 3.4.0 (default, Apr 11 2014, 13:05:18) > [GCC 4.8.2] on linux > Type "help", "copyright", "credits" or "license" for more information. >>>> code = """\ > ... s1 = 'first' > ... s2 = 'second' > ... """ >>>> exec(code) >>>> s1 > 'first' >>>> s2 > 'second' >>>> > > ..the following script also behaves as I expect: > alex@x301:~/Python$ cat test.py > #!/usr/bin/env python3 > """ > Testing use of exec(). > """ > code = """\ > s1 = 'first' > s2 = 'second' > """ > exec(code) > print(s1) > print(s2) > alex@x301:~/Python$ ./test.py > first > second > > ... but this one doesn't: > alex@x301:~/Python$ cat t1.py > #!/usr/bin/env python3 > """ > Testing use of exec(). > """ > code = """\ > s1 = 'first' > s2 = 'second' > """ > > def main(): > exec(code) > print(s1) > > if __name__ == "__main__": > main() > alex@x301:~/Python$ ./t1.py > Traceback (most recent call last): > File "./t1.py", line 15, in <module> > main() > File "./t1.py", line 12, in main > print(s1) > NameError: name 's1' is not defined > > Any light that can be shed onto this would be appreciated. > Alex
The function statically determines the scope of names. There is no assignment to s1 in main, thus s1 is supposed to be global. Unlike what one might expect exec("s1 = 42") binds the name s1 in the local namespace. On the module level the global and local namespace are identical >>> globals() is locals() True so you are effectively assigning a global variable. Inside a function there is no direct way to get access to the local namespace used by exec(). Your options are: - declare the variable as global >>> def f(): ... exec("global x; x = 42") ... print(x) ... >>> x Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'x' is not defined >>> f() 42 >>> x 42 - pass a dict to exec() >>> def f(): ... ns = {} ... exec("x = 42", ns) ... print(ns["x"]) ... >>> f() 42 PS: In Python 2 the situation was messy, too, but for this particular setup it worked as expected: >>> def f(): ... exec "x = 42" ... print x ... >>> x Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'x' is not defined >>> f() 42 >>> x Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'x' is not defined Because exec was a statement the compiler could generate different bytecode for functions containing exec. _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor