为什么我可以从'eval'调用'print'函数

7

对于代码:

#!/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个回答

7
< p > __import__ 方法被 import 关键字调用:python.org

如果你想要能够导入模块,必须将__import__方法保留在builtins中。

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

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

问题不是“为什么导入不起作用?”,而是“为什么打印能够正常工作?” - Tiendil
在Python 3k中,print变成了一个方法,我敢打赌以前的代码都不能用了 :) - Sacha

2

在您的eval中,成功调用了import,但是import使用了内置的__import__方法,而您在exec中禁用了该方法。这就是您看到错误的原因。

ImportError: __import__ not found

print不依赖于任何内置函数,因此可以正常工作。

您可以使用类似以下方式仅传递内置函数中的__import__

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

好的,但是为什么一个简单的语句(如文档中所述:http://docs.python.org/reference/simple_stmts.html)有适当的内置方法,而另一个没有呢?这种(架构上的?)解决方案是否有任何实际意义? - Tiendil
__import__ 方法存在的原因是,例如您可以替换它并更改 import 的语义。但是,最好使用导入钩子来完成此操作。请参见 http://docs.python.org/library/functions.html#__import__ 在 Python 3.x 中,print 已被 print() 内置方法所取代,因此您将在 3.x 中看到相同的行为。 - mikej

0

打印输出有效是因为您在compile函数调用时指定了'exec'参数。


0

import 调用全局/内置的 __import__ 函数;如果找不到该函数,则 import 失败。

print 不依赖于任何全局变量来完成其工作。这就是为什么在您的示例中即使没有使用可用的 __builtins__print 也可以正常工作的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接