exec(code) not allowing import on top level?

P

Peter Teuben

if I define a simple string code, with the following contents:

import math
def foo(x):
return math.sqrt(x)

and i run it using exec(code) in python, math is not known. But when I
recode the string as:

def foo(x):
import math
return math.sqrt(x)

it works fine. That seemed like an inconsistency, since it works
fine otherwise, as expected. It's easy to work around, but
just odd to find this out.

thanks

peter
 
G

Gary Herron

Peter said:
if I define a simple string code, with the following contents:

import math
def foo(x):
return math.sqrt(x)

What? You have not told us something important here. First, that code
won't fail because it does not even execute the function foo -- it just
defines it. Second, if I exend your string with one more line
"foo(123)" to actually execute the code, it still works as expected.

So let's try this again... and this time please please also show us the
full text of the error message.

Gary Herron
 
G

Gary Herron

Peter said:
if I define a simple string code, with the following contents:

import math
def foo(x):
return math.sqrt(x)

What? You have not told us something important here. First, that code
won't fail because it does not even execute the function foo -- it just
defines it. Second, if I extended your string with one more line
"foo(123)" to actually execute the code, it still works as expected.

So let's try this again... and this time please please also show us the
full text of the error message.

Gary Herron
 
S

Steven D'Aprano

if I define a simple string code, with the following contents:

import math
def foo(x):
return math.sqrt(x)

and i run it using exec(code) in python, math is not known.


Works for me.

.... def foo(x):
.... return math.sqrt(x)
.... """5.0

By the way, exec is a statement, not a function, so you don't need the
brackets.
 
P

Peter Otten

Peter said:
if I define a simple string code, with the following contents:

import math
def foo(x):
return math.sqrt(x)

The

import math

statement puts 'math' in the local namespace, and foo looks it up in the
global namespace. This can only work when these namespaces are the same:
.... import math
.... def foo(x):
.... return math.sqrt(x)
.... print foo(2)
.... """Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 5, in <module>
File "<string>", line 4, in foo
NameError: global name 'math' is not defined

You could argue that Python should always look into the local namespace and
then fall back to the global namespace but that would be fruitless extra
work in most cases. I think it can only hapen with exec/eval, and as you
have seen in the other responses even there it works on the module level
because -- tada!
True
and i run it using exec(code) in python, math is not known. But when I
recode the string as:

def foo(x):
import math
return math.sqrt(x)

Here Python "guesses" that math is a local variable and that guess is
correct. If you wrote

import math
def foo(x):
return math.sqrt(x)
math = 42

Python would still guess that math is a local name and you would end up with
a runtime exception.

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top