为什么eval尝试在__builtins__上下标?

时间:2018-08-02 19:01:07

标签: python

>>> eval('potato', {'__builtins__': None})
NameError: name 'potato' is not defined

Python2。很有意义。

>>> eval('potato', {'__builtins__': None})
TypeError: 'NoneType' object is not subscriptable

Python 3. eval如何/为什么尝试对None下标?我希望在这里使用相同的NameError,或者可能是AttributeError: 'NoneType' object has no attribute 'potato'

通过Python eval error

遇到

1 个答案:

答案 0 :(得分:2)

来自eval(expression, globals=None, locals=None) docs

  

如果存在globals字典且缺少“ __builtins__”,则   在解析表达式之前,将当前全局变量复制到全局变量中。   这意味着表达式通常可以完全访问标准   __builtin__模块和受限环境得以传播。

但是您正在将globals词典中的__builtins__设置为None,因此您的代码将求值为None['potato'],从而导致:

TypeError: 'NoneType' object is not subscriptable

编辑:

如果Python2.7在NameError-source code中找不到变量,则会引发__builtins__NAME_ERROR_MSG定义为:

#define NAME_ERROR_MSG \
"name '%.200s' is not defined"

Python3打印不同的消息-请参见source-PyObject_GetItem不会引发KeyError而是TypeError,因此字符串的格式不同,在这种情况下为TypeError: 'NoneType' object is not subscriptable

在CPython中,名称__builtins__可以绑定到模块或字典。那就是documented under the execution model

  

与代码块的执行相关的内建命名空间实际上是通过在其全局命名空间中查找名称__builtins__来找到的;这应该是字典或模块(在后一种情况下,将使用模块的字典)。