2016-10-22 6 views
0

В python 2.7 я мог бы ограничить пространство имен __builtins__, используемое eval, определяя глобальный как {'__builtins__': None}. Это не работает в Python 3.5.Как правильно ограничить __builtins__ в eval в Python 3.5?

Python 2.7 правильно дает NameError:

In [1]: eval('round', {'__builtins__': None}) 
--------------------------------------------------------------------------- 
NameError         Traceback (most recent call last) 
<ipython-input-14-dc1cae9c6b26> in <module>() 
----> 1 eval('round', {'__builtins__': None}) 

<string> in <module>() 

NameError: name 'round' is not defined 

Python 3.5 дает следующее:

In [1]: eval('round', {'__builtins__': None}) 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-9-83a8846287f1> in <module>() 
----> 1 eval('round', {'__builtins__': None}) 

<string> in <module>() 

TypeError: 'NoneType' object is not subscriptable 

Оба дают правильный выход для следующего:

In [1]: eval('round') 
Out[1]: <function round> 

Как я должным образом ограничить __builtins__ или обойти это?

ответ

2

Вы можете установить его в пустой словарь:

eval('round', {'__builtins__': {}}) 

Это воспроизводящего NameError вы получили в Python 2.x. Однако песочница Python, будь то 2 или 3, является inherently hard problem. Если возможно, вы должны использовать что-то менее мощное, например, ast.literal_eval() вместо eval().

+0

Отлично, спасибо. Есть ли другой способ оценки математических операций, например. '1 + 1'? AFIK, 'ast.literal_eval' этого не допускает. – mrclary

+0

Другие компоненты в 'ast' достаточно сильны, чтобы создать парсер для любого подмножества нужного вам языка ... но это может быть значительная работа, и вам нужно быть очень осторожным в разрешении доступа к атрибутам (т. Е. 'foo.bar' точечный синтаксис). – Kevin