views:

115

answers:

4

For code:

#!/usr/bin/python

src = """
print '!!!'
import os
"""

obj = compile(src, '', 'exec')
eval(obj, {'__builtins__': False})

I get output:

!!!
Traceback (most recent call last):
  File "./test.py", line 9, in <module>
    eval(obj, {'__builtins__': False})
  File "", line 3, in <module>

ImportError: __import__ not found

Both 'print' and 'import' are language construct. Why does 'eval' restrict using of 'import' but doesn't restrict 'print'?

P.S. I'm using python 2.6

UPDATE: Question is not "Why does import not work?" but "Why does print work?" Are there some architecture restrictions or something else?

+1  A: 

In your eval the call to import is made successfully however import makes use of the __import__ method in builtins which you have made unavailable in your exec. This is the reason why you are seeing

ImportError: __import__ not found

print doesn't depend on any builtins so works OK.

You could pass just __import__ from builtins with something like:

eval(obj, {'__builtins__' : {'__import__' :__builtins__.__import__}})
mikej
Ok, but why one simple statement (like said in documentation: http://docs.python.org/reference/simple_stmts.html) has appropriate builtin method, and another hasn't? Does this (architectural?) solution has any practical meaning?
Tiendil
`__import__` method exists so, for example, you can replace it and change the semantics of `import`. However this is better done using import hooks. See http://docs.python.org/library/functions.html#__import__ In Python 3.x `print` has been replaced with the `print()` builtin method so you would see the same behaviour with print in 3.x
mikej
+3  A: 

The __import__ method is invoked by the import keyword: python.org

If you want to be able to import a module you need to leave the __import__ method in the builtins:

src = """
print '!!!'
import os
"""

obj = compile(src, '', 'exec')
eval(obj, {'__builtins__': {'__import__':__builtins__.__import__}})
Sacha
Question is not "Why does import not work?" but "Why does print work?"
Tiendil
print becomes a method in python 3k, I bet it will not work anymore :)
Sacha
A: 

print works because you specified 'exec' to the compile function call.

Thud Foo
A: 

import calls the global/builtin __import__ function; if there isn't one to be found, import fails.

print does not rely on any globals to do its work. That is why print works in your example, even though you do not use the available __builtins__.

ΤΖΩΤΖΙΟΥ