What does Python's eval() do?

PythonEval

Python Problem Overview


In the book that I am reading on Python, it keeps using the code eval(input('blah'))

I read the documentation, and I understand it, but I still do not see how it changes the input() function.

What does it do? Can someone explain?

Python Solutions


Solution 1 - Python

The eval function lets a Python program run Python code within itself.

eval example (interactive shell):

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

Solution 2 - Python

eval() interprets a string as code. The reason why so many people have warned you about using this is because a user can use this as an option to run code on the computer. If you have eval(input()) and os imported, a person could type into input() os.system('rm -R *') which would delete all your files in your home directory. (Assuming you have a unix system). Using eval() is a security hole. If you need to convert strings to other formats, try to use things that do that, like int().

Solution 3 - Python

Lots of good answers here, but none describe the use of eval() in the context of its globals and locals kwargs, i.e. eval(expression, globals=None, locals=None) (see docs for eval here).

These can be used to limit the functions that are available through the eval function. For example if you load up a fresh python interpreter the locals() and globals() will be the same and look something like this:

>>>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. Let's take an example. 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)')
1

Ok. So there we see one function we want exposed and an example of one (of many that can be much more complex) method that we do not want exposed. So let's block everything.

>>>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)
8
>>>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.

N.B.

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]

Solution 4 - Python

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.

Solution 5 - Python

Maybe a misleading example of reading a line and interpreting it.

Try eval(input()) and type "1+1" - this should print 2. Eval evaluates expressions.

Solution 6 - Python

eval() evaluates the passed string as a Python expression and returns the result. For example, eval("1 + 1") interprets and executes the expression "1 + 1" and returns the result (2).

One reason you might be confused is because the code you cited involves a level of indirection. The inner function call (input) gets executed first so the user sees the "blah" prompt. Let's imagine they respond with "1 + 1" (quotes added for clarity, don't type them when running your program), the input function returns that string, which is then passed to the outer function (eval) which interprets the string and returns the result (2).

Read more about eval http://docs.python.org/library/functions.html#eval">here</a>;.

Solution 7 - Python

One of useful applications of eval() is to evaluate python expressions from string. For example load from file string representation of dictionary:

running_params = {"Greeting":"Hello "}
fout = open("params.dat",'w')
fout.write(repr(running_params))
fout.close()

Read it out as a variable and edit it:

fin = open("params.dat",'r')
diction=eval(fin.read())
diction["Greeting"]+="world"
fin.close()
print diction

Output:

{'Greeting': 'Hello world'}

Solution 8 - Python

eval(), as the name suggests, evaluates the passed argument.

raw_input() is now input() in python 3.x versions. So the most commonly found example for the use of eval() is its use to provide the functionality that input() provided in 2.x version of python. raw_input returned the user-entered data as a string, while input evaluated the value of data entered and returned it.

eval(input("bla bla")) thus replicates the functionality of input() in 2.x, i.e., of evaluating the user-entered data.

In short: eval() evaluates the arguments passed to it and hence eval('1 + 1') returned 2.

Solution 9 - Python

I'm late to answer this question but, no one seems to give clear answer to the question.

If an user enters a numeric value, input() will return a string.

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

So, eval() will evaluate returned value (or expression) which is a string and return integer/float.

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

Of cource this is a bad practice. int() or float() should be used instead of eval() in this case.

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

Solution 10 - Python

Another option if you want to limit the evaluation string to simple literals is to use ast.literal_eval(). Some examples:

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: but only works due to a quirk in parser
# print(ast.literal_eval('1*1'))       # ValueError: malformed node or string
print(ast.literal_eval("{'a':1}"))     # {'a':1}

From the docs:

> Safely evaluate an expression node or a string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None. > > This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.

As for why it's so limited, from the mailing list:

> Allowing operator expressions with literals is possible, but much more complex than the current implementation. A simple implementation is not safe: you can induce basically unbounded CPU and memory usage with no effort (try "9*9*9" or "[None] * 9**9"). > > As for the usefulness, this function is useful to "read back" literal values and containers as stringified by repr(). This can for example be used for serialization in a format that is similar to but more powerful than JSON.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBilljkView Question on Stackoverflow
Solution 1 - PythonBYS2View Answer on Stackoverflow
Solution 2 - PythonCoffeeRainView Answer on Stackoverflow
Solution 3 - PythonGrrView Answer on Stackoverflow
Solution 4 - PythonzeekayView Answer on Stackoverflow
Solution 5 - PythonhburdeView Answer on Stackoverflow
Solution 6 - PythonMarc CohenView Answer on Stackoverflow
Solution 7 - PythonNikolay FrickView Answer on Stackoverflow
Solution 8 - PythonRubalView Answer on Stackoverflow
Solution 9 - PythonCalvin KimView Answer on Stackoverflow
Solution 10 - PythonBrian BurnsView Answer on Stackoverflow