Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why I can call 'print' from 'eval'

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?

like image 267
Tiendil Avatar asked Oct 16 '10 16:10

Tiendil


2 Answers

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__}})
like image 170
Sacha Avatar answered Oct 22 '22 23:10

Sacha


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__}})
like image 35
mikej Avatar answered Oct 22 '22 22:10

mikej