Поиск…


Синтаксис

  • eval (выражение [, globals = None [, locals = None]])
  • Exec (объект)
  • exec (объект, глобальные переменные)
  • exec (объект, globals, locals)

параметры

аргументация подробности
expression Код выражения как строка или объект code
object Код оператора как строка или объект code
globals Словарь для использования для глобальных переменных. Если местные жители не указаны, это также используется для местных жителей. Если этот параметр опущен, используются globals() зоны вызова.
locals Объект сопоставления, который используется для локальных переменных. Если этот параметр опущен, вместо него используется тот, который передается для globals . Если оба они опущены, то globals() и locals() области вызова используются для globals и locals соответственно.

замечания

В exec , если globals являются locals (т.е. они относятся к одному и тому же объекту), код выполняется так, как если бы он находился на уровне модуля. Если globals и locals объекты являются отдельными объектами, код выполняется так, как если бы он находился в классе класса .

Если объект globals передан, но не указывает ключ __builtins__ , тогда встроенные функции и имена Python автоматически добавляются в глобальную область. Чтобы подавить доступность таких функций, как print или isinstance в выполненной области, пусть globals ключи имеют ключ __builtins__ отображаемый для значения None . Однако это не функция безопасности.

Синтаксис Python 2 не должен использоваться; синтаксис Python 3 будет работать в Python 2. Таким образом, следующие формы устарели: <s>

  • exec object
  • exec object in globals
  • exec object in globals, locals

Оценка операторов с помощью exec

>>> code = """for i in range(5):\n    print('Hello world!')"""
>>> exec(code)
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!

Оценка выражения с помощью eval

>>> expression = '5 + 3 * a'
>>> a = 5
>>> result = eval(expression)
>>> result
20

Предварительная компиляция выражения для его оценки несколько раз

встроенная функция compile может быть использована для прекомпиляции выражения для объекта кода; этот объект кода затем может быть передан в eval. Это ускорит повторные исполнения оцененного кода. Третий параметр для compile должен быть строкой 'eval' .

>>> code = compile('a * b + c', '<string>', 'eval')
>>> code
<code object <module> at 0x7f0e51a58830, file "<string>", line 1>
>>> a, b, c = 1, 2, 3
>>> eval(code)
5

Оценка выражения с помощью eval с использованием пользовательских глобальных переменных

>>> variables = {'a': 6, 'b': 7}
>>> eval('a * b', globals=variables)
42

В качестве плюса с этим код не может случайно ссылаться на имена, определенные вне:

>>> eval('variables')
{'a': 6, 'b': 7}
>>> eval('variables', globals=variables)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'variables' is not defined

Использование defaultdict позволяет, например, иметь неопределенные переменные, установленные на ноль:

>>> from collections import defaultdict
>>> variables = defaultdict(int, {'a': 42})
>>> eval('a * c', globals=variables)  # note that 'c' is not explicitly defined
0

Оценка строки, содержащей литерал Python с помощью ast.literal_eval

Если у вас есть строка, содержащая литералы Python, такие как строки, float и т. Д., Вы можете использовать ast.literal_eval для оценки ее значения вместо eval . Это добавляет возможность разрешать только определенный синтаксис.

>>> import ast
>>> code = """(1, 2, {'foo': 'bar'})"""
>>> object = ast.literal_eval(code)
>>> object
(1, 2, {'foo': 'bar'})
>>> type(object)
<class 'tuple'>

Тем не менее, это небезопасно для выполнения кода, предоставленного ненадежным пользователем, и тривиально сбрасывать интерпретатор с помощью тщательно обработанного ввода

>>> import ast
>>> ast.literal_eval('()' * 1000000)
[5]    21358 segmentation fault (core dumped)  python3

Здесь вход представляет собой строку () повторяющуюся один миллион раз, что вызывает сбой в парсере CPython. Разработчики CPython не рассматривают ошибки в парсере как проблемы безопасности.

Выполнение кода, предоставленного ненадежным пользователем с помощью exec, eval или ast.literal_eval

Невозможно использовать eval или exec для безопасного выполнения кода от ненадежного пользователя. Даже ast.literal_eval склонен к сбоям в парсере. Иногда можно защитить от выполнения вредоносного кода, но это не исключает возможности прямых сбоев в парсере или токенизаторе.

Чтобы оценить код ненадежным пользователем, вам нужно обратиться к стороннему модулю или, возможно, написать собственный парсер и свою собственную виртуальную машину в Python.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow