What does Python's eval() do?

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

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

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

Что это делает? Кто-нибудь может объяснить?

Переведено автоматически
Ответ 1

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

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

>>> x = 1
>>> eval('x + 1')
>>> eval('x')
Ответ 2

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

Ответ 3

Как описано в документации, eval() также имеет аргументы ключевого слова globals и locals, которые могут использоваться для ограничения функций, доступных через eval функцию. Например, если вы загрузите новый интерпретатор Python, то locals() и globals() будут такими же и будут выглядеть примерно так:

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

There are certainly functions within the builtins module that can do significant damage to a system. But it is possible to block anything and everything we don't want available. Say we want to construct a list to represent a domain of the available cores on a system. For me I have 8 cores, so I would want a list [1, 8].

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

Likewise all of __builtins__ is available.

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

Let's try blocking access to any globals:

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

We have effectively blocked all of the __builtins__ functions and as such brought a level of protection into our system. At this point we can start to add back in functions that we do want exposed.

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

Now we have the cpu_count function available while still blocking everything we do not want. In my opinion, this is super powerful and clearly from the scope of the other answers, not a common implementation. There are numerous uses for something like this and as long as it is handled correctly, I personally feel eval can be safely used to great value.


Something else that is cool about these kwargs is that you can start to use shorthand for your code. Let's say you use eval as part of a pipeline to execute some imported text. The text doesn't need to have exact code, it can follow some template file format, and still execute anything you'd like. For example:

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

In Python 2.x input(...) is equivalent to eval(raw_input(...)), in Python 3.x raw_input was renamed input, which I suspect lead to your confusion (you were probably looking at the documentation for input in Python 2.x). Additionally, eval(input(...)) would work fine in Python 3.x, but would raise a TypeError in Python 2.

In this case eval is used to coerce the string returned from input into an expression and interpreted. Generally this is considered bad practice.