Python exec globals and locals

Метод exec() в Python

По сути, метод Python exec() выполняет переданный набор кода в виде строки. Это очень полезно, так как практически поддерживает динамическое выполнение. Синтаксис метода приведен ниже.

exec(object, globals, locals)

Здесь object может быть строкой, объектом открытого файла или объектом кода.

  • Для строки — строка анализируется как набор операторов Python, который затем выполняется (если не возникает синтаксическая ошибка).
  • Для открытого файла — файл анализируется до EOF и выполняется.
  • Для объекта кода — просто выполняется.

И два дополнительных аргументов globals и locals должны быть словари , используемые для глобальных и локальных переменных.

Exec() метод

Давайте попробуем понять, как он работает, на примере.

>>> exec("print('Hey!')") Hey! >>> exec("print(6+4)") 10

Из приведенного выше фрагмента кода ясно, что операторы print() успешно выполняются методом exec() и мы получаем желаемые результаты.

Работа с методом Python exec()

Теперь давайте сразу перейдем к некоторым примерам, изучающим, как метод exec() работает в Python с параметрами globals и locals и без них.

1 Без глобальных и локальных параметров

В предыдущем примере мы просто выполнили некоторый набор инструкций в Python, передав аргумент объекта методу exec() . Но мы не видели имена в текущей области.

Теперь давайте воспользуемся методом dir(), чтобы получить список текущих методов и имен с включенным math модулем перед вызовом метода exec() .

from math import * exec("print(pow(2, 5))") exec("print(dir())")
32.0 ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

Как видите, различные методы, включая builtins , а также из math модуля, прямо сейчас находятся в текущей области видимости и доступны для метода exec() .

Это создает большую проблему безопасности, когда вы думаете о выполнении динамического кода Python. Пользователь может включать некоторые модули для доступа к системным командам, которые даже могут привести к сбою вашего компьютера.

Используя параметры globals и locals мы можем буквально ограничить exec() чтобы выйти за пределы методов, к которым мы хотим получить доступ.

2 С параметром globals

Python позволяет нам передавать и указывать только те методы, к которым мы хотим, чтобы метод exec() имел доступ (в форме словаря) из встроенного модуля.

def squareNo(a): return a*a exec('print(squareit(10))',>) exec("print(dir())")
100 ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'squareNo']

В приведенном выше коде мы передали словарь, содержащий методы squareNo() (сопоставленные с настраиваемым именем squareit) и print() .

Обратите внимание: использование любого другого метода из встроенного метода вызовет TypeError .

3 С параметром locals

Когда мы передаем только local параметр (словарь), по умолчанию все встроенные методы также становятся доступными до тех пор, пока мы явно не исключим их.

Посмотрите на пример ниже, хотя мы указали словарь locals все встроенные и математические методы модуля доступны в текущей области.

from math import * def squareNo(a): return a*a #global And local parameters exec('print(pow(4,3))', ) exec("print(dir())")
64 ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'squareNo', 'tan', 'tanh', 'tau', 'trunc']

Следовательно, теперь явно исключая встроенные функции.

from math import * def squareNo(a): return a*a #explicitly excluding built-ins exec('print(pow(4,3))', ,) exec("print(dir())")
Traceback (most recent call last): File "C:/Users/sneha/Desktop/test.py", line 7, in exec('print(pow(4,3))', ,) File "", line 1, in TypeError: 'NoneType' object is not subscriptable

В приведенном выше коде ограничение метода на использование только переданных (локальных) методов практически делает недоступным метод pow() . Следовательно, при его запуске мы получаем TypeError .

exec() сравнение с eval()

Между методами eval() и exec() есть два основных различия, хотя они выполняют почти одинаковую работу.

  1. eval() может выполнять только одно выражение, тогда как exec() может использоваться для выполнения динамически созданного оператора или программы, которая может включать циклы, операторы if-else , определения функций и class ,
  2. eval() возвращает значение после выполнения определенного выражения, тогда как exec() в основном ничего не возвращает и просто игнорирует значение.

Источник

Читайте также:  What is structured programming in java
Оцените статью