Функция eval()
используется для синтаксического анализа строк выражения Python и последующего выполнения.
Синтаксис:
eval(expression, globals=None, locals=None)
Аргументы:
expression
- является обязательным строковым параметром, анализируется и выполняется как выражение Python.globals
- это словарь, используемый для определения того, какие выражения доступны для выполнения. Встроенные методы по умолчанию доступны, если они явно не ограничены элементом __builtins__: None.locals
- используется для указания локальных переменных и методов, доступных для функцииeval()
.
Рассмотрим простой пример с eval()
:
x = 1
print(eval('x == 1'))
print(eval('x + 4'))
Результат:
>>> True
>>> 5
Приведенный выше пример функции eval()
очень ограничен и не оправдывает ее возможностей.
Сила функции заключается в динамическом выполнении операторов. Мы можем выполнять произвольные объекты кода с помощью функции eval()
.
Давайте рассмотрим более сложный пример, в котором мы попросим пользователя ввести функции для выполнения.
from math import *
for l in range(1, 3):
func = input("Enter Math Function to Evaluate:\n")
try:
print(eval(func))
except Exception as ex:
print(ex)
break
print('Done')
Результат выполнения:
<<< Enter Math Function to Evaluate:
>>> 5
>>> 5
<<< Enter Math Function to Evaluate:
>>> 6
>>> 6
>>> Done
Без функции eval()
мы не можем выполнять команды, введенные пользователем. В этом сила функции eval().
Угрозы безопасности
Что делать, если у нас есть импортированный модуль os, и пользователь вводит команду os.system('rm -rf /')
для выполнения. Это сотрет системные файлы и повредит нашу среду. Вот почему, когда вы используете функцию eval()
для выполнения кода пользовательского ввода, вам нужно убедиться, что сначала проверяется пользовательский ввод, и если он в порядке, то выполняется только он.
Вот когда глобальные и локальные параметры пригодятся.
Прежде чем решить, какие функции мы должны сделать доступными для eval()
, нам нужно определить, какие функции и переменные присутствуют в глобальной и локальной области видимости.
Мы можем найти эту информацию, используя встроенные функции locals()
, globals()
и dir()
.
Давайте рассмотрим пример, в котором мы изучим функции и переменные, доступные в глобальной и локальной области видимости.
from math import *
def square_root(n):
return sqrt(n)
print(globals())
print(locals())
print(dir())
Результат:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000015D481489A0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (bu
ilt-in)>, '__file__': 'C:\\Users\\Razilator\\Desktop\\Courses\\nth-coding\\articles\\eval\\main.py', '__cached__': None, 'acos': <built-in function acos>, 'acosh': <built-in function acosh>, 'asin': <built-in function asin>, 'asinh'
: <built-in function asinh>, 'atan': <built-in function atan>, 'atan2': <built-in function atan2>, 'atanh': <built-in function atanh>, 'ceil': <built-in function ceil>, 'copysign': <built-in function copysign>, 'cos': <built-in func
tion cos>, 'cosh': <built-in function cosh>, 'degrees': <built-in function degrees>, 'dist': <built-in function dist>, 'erf': <built-in function erf>, 'erfc': <built-in function erfc>, 'exp': <built-in function exp>, 'expm1': <built
-in function expm1>, 'fabs': <built-in function fabs>, 'factorial': <built-in function factorial>, 'floor': <built-in function floor>, 'fmod': <built-in function fmod>, 'frexp': <built-in function frexp>, 'fsum': <built-in function
fsum>, 'gamma': <built-in function gamma>, 'gcd': <built-in function gcd>, 'hypot': <built-in function hypot>, 'isclose': <built-in function isclose>, 'isfinite': <built-in function isfinite>, 'isinf': <built-in function isinf>, 'is
nan': <built-in function isnan>, 'isqrt': <built-in function isqrt>, 'lcm': <built-in function lcm>, 'ldexp': <built-in function ldexp>, 'lgamma': <built-in function lgamma>, 'log': <built-in function log>, 'log1p': <built-in functi
on log1p>, 'log10': <built-in function log10>, 'log2': <built-in function log2>, 'modf': <built-in function modf>, 'pow': <built-in function pow>, 'radians': <built-in function radians>, 'remainder': <built-in function remainder>, '
sin': <built-in function sin>, 'sinh': <built-in function sinh>, 'sqrt': <built-in function sqrt>, 'tan': <built-in function tan>, 'tanh': <built-in function tanh>, 'trunc': <built-in function trunc>, 'prod': <built-in function prod
>, 'perm': <built-in function perm>, 'comb': <built-in function comb>, 'nextafter': <built-in function nextafter>, 'ulp': <built-in function ulp>, 'pi': 3.141592653589793, 'e': 2.718281828459045, 'tau': 6.283185307179586, 'inf': inf, 'nan': nan, 'square_root': <function square_root at 0x0000015D4819EF80>}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000015D481489A0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (bu
ilt-in)>, '__file__': 'C:\\Users\\Razilator\\Desktop\\Courses\\nth-coding\\articles\\eval\\main.py', '__cached__': None, 'acos': <built-in function acos>, 'acosh': <built-in function acosh>, 'asin': <built-in function asin>, 'asinh'
: <built-in function asinh>, 'atan': <built-in function atan>, 'atan2': <built-in function atan2>, 'atanh': <built-in function atanh>, 'ceil': <built-in function ceil>, 'copysign': <built-in function copysign>, 'cos': <built-in func
tion cos>, 'cosh': <built-in function cosh>, 'degrees': <built-in function degrees>, 'dist': <built-in function dist>, 'erf': <built-in function erf>, 'erfc': <built-in function erfc>, 'exp': <built-in function exp>, 'expm1': <built
-in function expm1>, 'fabs': <built-in function fabs>, 'factorial': <built-in function factorial>, 'floor': <built-in function floor>, 'fmod': <built-in function fmod>, 'frexp': <built-in function frexp>, 'fsum': <built-in function
fsum>, 'gamma': <built-in function gamma>, 'gcd': <built-in function gcd>, 'hypot': <built-in function hypot>, 'isclose': <built-in function isclose>, 'isfinite': <built-in function isfinite>, 'isinf': <built-in function isinf>, 'is
nan': <built-in function isnan>, 'isqrt': <built-in function isqrt>, 'lcm': <built-in function lcm>, 'ldexp': <built-in function ldexp>, 'lgamma': <built-in function lgamma>, 'log': <built-in function log>, 'log1p': <built-in functi
on log1p>, 'log10': <built-in function log10>, 'log2': <built-in function log2>, 'modf': <built-in function modf>, 'pow': <built-in function pow>, 'radians': <built-in function radians>, 'remainder': <built-in function remainder>, '
sin': <built-in function sin>, 'sinh': <built-in function sinh>, 'sqrt': <built-in function sqrt>, 'tan': <built-in function tan>, 'tanh': <built-in function tanh>, 'trunc': <built-in function trunc>, 'prod': <built-in function prod
>, 'perm': <built-in function perm>, 'comb': <built-in function comb>, 'nextafter': <built-in function nextafter>, 'ulp': <built-in function ulp>, 'pi': 3.141592653589793, 'e': 2.718281828459045, 'tau': 6.283185307179586, 'inf': inf, 'nan': nan, 'square_root': <function square_root at 0x0000015D4819EF80>}
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'de
grees', 'dist', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'lcm', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'nextafter', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'square_root', 'tan', 'tanh', 'tau', 'trunc', 'ulp']
Это набор функций, к которым будет иметь доступ eval()
. Большинство из них поступают из модулей __builtins__
и math
. Давайте посмотрим, что произойдет, если мы укажем globals как пустой словарь в функции eval()
print(eval('dir()', {}))
Результат:
['__builtins__']
Таким образом, встроенные методы по-прежнему доступны для функции eval
.
Если вы хотите ограничить доступ только к нескольким встроенным методам, вы можете указать их значение для глобальных переменных. Например, следующий код позволяет функции eval()
выполнять только встроенную функцию min.
print(eval('min(1,2)',{'__builtins__':{'min': min}}))
Давайте посмотрим на другой пример, где я предоставляю локальное значение и отключаю доступ к любым встроенным функциям для eval()
.
y = 5
print(eval('y+1',{'__builtins__': None}, {'y': y}))
Давайте посмотрим на последний пример, в котором я разрешаю доступ только к некоторым методам из математического модуля. Мы также сопоставляем square_root
с функцией sqrt
для удобства чтения человеком.
from math import *
for l in range(1, 3):
func = input("Enter Math Function to Evaluate.\nAllowed Functions are: square_root(x) and pow(x,y):\n")
try:
print(eval(func, {'square_root': sqrt, 'pow': pow}))
except Exception as ex:
print(ex)
break
print('Done')
Результат:
Enter Math Function to Evaluate.
Allowed Functions are: square_root(x) and pow(x,y):
square_root(16)
4.0
Enter Math Function to Evaluate.
Allowed Functions are: square_root(x) and pow(x,y):
log10(100)
name 'log10' is not defined
Done
Источник: pythonim.ru