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

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

Я прочитал документацию, и я понимаю это, но я все еще не вижу, как это меняет input() функция.

Что оно делает? Может кто-нибудь объяснить?

12 ответов

Решение

Функция 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(),

Здесь много хороших ответов, но ни один не описывает использование eval() в контексте его globals а также locals Кварги, т.е. eval(expression, globals=None, locals=None) (см. документы для eval здесь)

Их можно использовать для ограничения методов, доступных через 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

Хорошо. Таким образом, мы видим один метод, который мы хотим раскрыть, и пример одного (из многих, который может быть гораздо более сложного) метода, который мы не хотим раскрывать. Итак, давайте заблокируем все.

>>>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 может быть безопасно использован для большой стоимости.

NB

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

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

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

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

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() чтобы оценить выражения 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'}

Другой вариант, если вы хотите ограничить строку оценки простыми выражениями, это использовать ast.literal_eval():

import ast

# print(ast.literal_eval(''))          # SyntaxError: unexpected EOF while parsing
# print(ast.literal_eval('a'))         # ValueError: malformed node or string
# print(ast.literal_eval('import os')) # SyntaxError: invalid syntax
print(ast.literal_eval('1+1'))         # 2

Смотрите документы здесь.

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

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

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

Так, eval() оценит возвращаемое значение (или выражение), которое является строкой, и вернет целое число / число с плавающей запятой.

>>> 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

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

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

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

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

Узнайте больше о Eval здесь.

Функция eval() принимает три параметра, оценивает и возвращает значение.
синтаксис: eval(выражение, глобальные переменные, локальные переменные)
выражение #строка глобальных переменных выражения python3
(необязательно) #
локальные переменные словаря (необязательно) #словарь
#общий вариант использования, который вы часто используете, это
x="{'name':'abhi','mydict':{'sub':'python'}}"
y=dict(x)
print(y,type(y)) # ValueError: dictionary update sequence element #0 has length 1; 2 is required
z=eval(x)
print(z,type(z)) #{'name': 'abhi', 'mydict': {'sub': 'python'}} <class 'dict'>

Обратите внимание на разницуeval()иexec():

      >>> exec("x=2")
>>> x
2
>>> eval("x=1")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    x=1
     ^
Другие вопросы по тегам