Что делает eval () Python?

в книге, которую я читаю на Python, он продолжает использовать код eval(input('blah'))

Я читаю документацию, и я ее понимаю, но я до сих пор не вижу, как она меняет

9 ответов


функция eval позволяет программе Python запускать код Python внутри себя.

пример eval (интерактивная оболочка):

>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1

eval() интерпретирует строку как код. Причина, по которой так много людей предупредили вас об использовании этого, заключается в том, что пользователь может использовать это в качестве опции для запуска кода на компьютере. Если у вас есть eval(input()) и os импортировано, человек может ввести в input() os.system('rm -R *') который удалит все ваши файлы в вашем домашнем каталоге. (Предполагая, что у вас есть система unix). Используя eval() дыра в безопасности. Если вам нужно преобразовать строки в другие форматы, попробуйте использовать вещи, которые это делают, например int().


В Python 2.x input(...) эквивалентно eval(raw_input(...)), в Python 3.x raw_input была переименована в input, что, как я подозреваю, приводит к вашей путанице (вы, вероятно, просматривали документацию для input в Python 2.икс.) Кроме того, eval(input(...)) будет работать в Python 3.x, но поднимет a TypeError в Python 2.

в этом случае eval используется для принуждения строки, возвращенной из input в выражении и интерпретации. Обычно это считается плохой практикой.


много хороших ответов здесь, но ни один не описывает использование eval в контексте globals= и locals= kwargs. Они могут использоваться для ограничения методов, доступных через eval метод. Например, если вы загружаете новый интерпретатор python, то locals() и globals() будет то же самое и выглядеть примерно так:

>>> globals()
{'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__doc__': None,
 '__spec__': None, '__builtins__': <module 'builtins' (built-in)>,
 '__package__': None, '__name__': '__main__'}

есть, конечно, методы в рамках builtins модуль, который может нанести значительный ущерб системе. Но возможно заблокируйте все, что нам не нужно. Возьмем пример. Скажем, мы хотим построить список для представления домена доступных ядер в системе. Для меня у меня есть 8 ядер, поэтому мне нужен список [1, 8].

>>>from os import cpu_count()
>>>eval('[1, cpu_count()'])
[1, 8]

дополнительно все __builtins__ доступно.

>>>eval('abs(-1)')
1

Ok. Таким образом, мы видим один метод, который мы хотим разоблачить, и пример одного (из многих, которые могут быть гораздо более коварными) метода, который мы не хотим разоблачать. Так давайте блокировать всё.

>>>eval('[1, cpu_count()]', {'__builtins__':None}, {})
TypeError: 'NoneType' object is not subscriptable

мы эффективно заблокировали все __builtins__ методы и как таковые принесли уровень защиты в нашу систему. На этом этапе мы можем начать добавлять обратно методы,которые мы хотим выставить.

>>>from os import cpu_count
>>>exposed_methods = {'cpu_count': cpu_count}
>>>eval('cpu_count()', {'__builtins__':None}, exposed_methods)
8
>>>eval('abs(cpu_count())', {'__builtins__':None}, exposed_methods)
TypeError: 'NoneType' object is not subscriptable

теперь у нас есть метод cpu_count доступен, все еще блокируя все, что мы не хотим. На мой взгляд, это супер мощный и явно из области других ответов не общая реализация. Есть множество применений для что-то вроде этого и до тех пор, пока оно обрабатывается правильно, я лично чувствую eval можно безопасно использовать к большому значению.

Б. Н.

что-то еще, что круто об этих kwargs это то, что вы можете начать использовать стенографию для своего кода. Предположим, вы используете eval как часть конвейера для выполнения некоторого импортированного текста. Текст не должен иметь точный код, он может следовать формату файла шаблона и выполнять все, что вы хотите. Для пример:

>>>from os import cpu_count
>>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]

eval() анализирует переданную строку как выражение Python и возвращает результат. Например, eval("1 + 1") интерпретирует и выполняет выражение "1 + 1" и возвращает результат (2).

одна из причин, по которой вы можете быть смущены, заключается в том, что приведенный вами код включает в себя уровень косвенности. Внутренний вызов функции (ввод) выполняется первым, поэтому пользователь видит приглашение "бла". Давайте представим, что они отвечают "1 + 1 "(кавычки добавлены для ясности, не вводите их при запуске program), функция ввода возвращает эту строку, которая затем передается внешней функции (eval), которая интерпретирует строку и возвращает результат (2).

подробнее об eval здесь.


eval(), как следует из названия, оценивает переданный аргумент.

raw_input() теперь input() в python 3.X версий. Таким образом, наиболее часто встречающийся пример использования eval() его использование для обеспечения функциональности, которая input() в 2.x версия python. raw_input вернул введенные пользователем данные в виде строки, а input оценил значение введенных данных и вернул его.

eval(input("bla bla")) таким образом, реплицирует функциональность input() в 2.x, т. е. оценка введенных пользователем данных.

короче: eval() оценивает переданные ему Аргументы и, следовательно,eval('1 + 1') возвращены 2.


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

попробовать eval(input()) и типа "1+1" - это должно вывести 2. Eval оценивает выражения.


одно из полезных приложений eval() - Это оценка выражений python из строки. Например, загрузить из файла строковое представление словаря:

running_params = {"Greeting":"Hello "}

fout = open("params.dat",'w')

fout.write(repr(running_params))

fout.close()

читать его как переменную и изменить ее:

fin = open("params.dat",'r')

diction=eval(fin.read())

diction["Greeting"]+="world"

fin.close()

print diction

выход:

{'Greeting': 'Hello world'}

Я опаздываю, чтобы ответить на этот вопрос, но, похоже, никто не дает четкого ответа на этот вопрос.

если пользователь вводит числовое значение, input() вернет строку.

>>> input('Enter a number: ')
Enter a number: 3
>>> '3'
>>> input('Enter a number: ')
Enter a number: 1+1
'1+1'

и eval() будет оценивать возвращаемое значение (или выражение), которое является строкой и возвращает целое число/float.

>>> eval(input('Enter a number: '))
Enter a number: 1+1
2
>>> 
>>> eval(input('Enter a number: '))
Enter a number: 3.14
3.14

конечно, это плохая практика. int() или float() вместо eval() в этом случае.

>>> float(input('Enter a number: '))
Enter a number: 3.14
3.14