为什么我能从'eval'中调用'print

7 投票
4 回答
3537 浏览
提问于 2025-04-16 05:36

对于这段代码:

#!/usr/bin/python

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

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

我得到的输出是:

!!!
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

‘print’和‘import’都是语言的基本构造。为什么‘eval’限制使用‘import’,但不限制‘print’呢?

附注:我使用的是Python 2.6

更新:问题不是“为什么import不工作?”而是“为什么print可以工作?”这背后是否有一些架构上的限制或者其他原因?

4 个回答

0

import 是用来调用一个叫做 __import__ 的全局函数;如果找不到这个函数,import 就会失败。

print 则不需要依赖任何全局变量来完成它的工作。这就是为什么在你的例子中,print 能正常工作,即使你没有使用可用的 __builtins__

2

在你的 eval 里,调用 import 是成功的,但 import 实际上是使用了内置的 __import__ 方法,而你在 exec 中把这个方法给禁用了。这就是你看到的原因。

ImportError: __import__ not found

print 不依赖任何内置方法,所以可以正常工作。

你可以通过类似下面的方式,从内置中传递 __import__

eval(obj, {'__builtins__' : {'__import__' :__builtins__.__import__}})
7

__import__ 方法是通过 import 这个关键词来调用的: python.org

如果你想要能够导入一个模块,你需要把 __import__ 方法放在内置函数里:

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

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

撰写回答