python exec behaves inconsistent with respect to module imports
Peter Otten
__peter__ at web.de
Wed Sep 5 10:11:12 EDT 2007
Am Wed, 05 Sep 2007 13:12:24 +0000 schrieb carl.dhalluin at gmail.com:
> I am completely puzzled why the following exec code does not work:
>
> mycode = "import math\ndef f(y):\n print math.floor(y)\nf(3.14)"
> def execute():
> exec mycode
> execute()
>
>
> I get the error:
>
> root at devmachine1:/opt/qbase# python error1.py
> Traceback (most recent call last):
> File "error1.py", line 5, in ?
> execute()
> File "error1.py", line 4, in execute
> exec mycode
> File "<string>", line 4, in ?
> File "<string>", line 3, in f
> NameError: global name 'math' is not defined
> Note that the following code _does_ work:
>
> mycode = "import math\ndef f(y):\n print math.floor(y)\nf(3.14)"
> exec mycode
> I have tested this in python 2.3 and 2.4.
exec breaks nested namespaces here.
Essentially
exec "import math"
puts the "math" name into the local namespace, but
"def f(): math.floor"
looks up "math" in the global namespace. On the module level global and
local namespace are identical
>>> globals() is locals()
True
but inside a function they are distinct
>>> def f(): return globals() is locals()
...
>>> f()
False
A workaround is to declare "math" as global:
>>> s = """
... global math
... import math
... def f(y): print math.floor(y)
... f(3.14)
... """
>>> def execute():
... exec s
...
>>> execute()
3.0
or pass it explicitly:
[new interpreter session]
>>> s = """
... import math
... def f(y, math=math): print math.floor(y)
... f(3.14)
... """
>>> def execute():
... exec s
...
>>> execute()
3.0
Peter
More information about the Python-list
mailing list