问题:Python的eval()有什么作用?

在我用Python阅读的书中,它一直在使用代码 eval(input('blah'))

我阅读了文档,但我理解了它,但仍然看不到它如何更改input()功能。

它有什么作用?有人可以解释吗?

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?


回答 0

eval函数允许Python程序在其内部运行Python代码。

评估示例(交互式外壳):

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

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

回答 1

eval()将字符串解释为代码。之所以有如此多的人警告您使用此功能,是因为用户可以将其用作在计算机上运行代码的选项。如果你有eval(input())os进口的,一个人可以键入input() os.system('rm -R *')这将删除你的家目录中的所有文件。(假设您有一个Unix系统)。使用eval()是一个安全漏洞。如果您需要将字符串转换为其他格式,请尝试使用可实现此目的的东西int()

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


回答 2

这里有很多很好的答案,但没有一个描述在eval()globalslocalskwargs 的上下文中的使用,即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]

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]

回答 3

在Python 2.x input(...)中等效于eval(raw_input(...)),在Python 3.x中raw_input已重命名input,我怀疑这会引起您的困惑(您可能正在查看inputPython 2.x 的文档)。此外,eval(input(...))在Python 3.x中可以正常工作,但TypeError在Python 2中可以提高a 。

在这种情况下eval,用于强制将返回的字符串input转换为表达式并进行解释。通常,这被认为是不良做法。

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.


回答 4

也许是读一行并解释它的一个令人误解的例子。

尝试eval(input())输入"1+1"-这应该打印出来2。Eval计算表达式。

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.


回答 5

eval()将传递的字符串评估为Python表达式并返回结果。例如,eval("1 + 1")解释并执行表达式"1 + 1"并返回结果(2)。

您可能会感到困惑的一个原因是,您引用的代码涉及一种间接级别。内部函数调用(输入)首先执行,因此用户看到“ blah”提示。假设它们以“ 1 +1”响应(为清楚起见添加了引号,请在运行程序时不要键入它们),输入函数返回该字符串,然后将其传递给外部函数(eval),该函数解释该字符串并返回结果(2)。

在此处阅读有关eval的更多信息。

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


回答 6

eval()顾名思义,它评估传递的参数。

raw_input()现在input()是python 3.x版本。因此,最常见的使用示例eval()是它用于提供input()python 2.x版本提供的功能。raw_input以字符串的形式返回用户输入的数据,而input评估输入的数据的值并返回它。

eval(input("bla bla"))因此复制了input()2.x中的功能,即评估用户输入的数据。

简而言之:eval()计算传递给它的参数并因此eval('1 + 1')返回2。

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.


回答 7

的有用应用之一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'}

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

回答 8

我迟迟未回答这个问题,但是似乎没人能给出明确的答案。

如果用户输入数字值,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

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

回答 9

如果要将评估字符串限制为简单文字,则可以使用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: 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}

文档

安全地评估表达式节点或包含Python文字或容器显示的字符串。提供的字符串或节点只能由以下Python文字结构组成:字符串,字节,数字,元组,列表,字典,集合,布尔值和无。

这可用于安全地评估包含来自不受信任来源的Python值的字符串,而无需自己解析值。它不能评估任意复杂的表达式,例如涉及运算符或索引的表达式。

至于为什么如此有限,请从邮件列表中进行

允许带有文字的运算符表达式是可能的,但是比当前实现复杂得多。一个简单的实现并不安全:您可以毫不费力地诱导CPU和内存的使用不受限制(尝试“ 9 ** 9 ** 9”或“ [无] * 9 ** 9”)。

至于有用性,此函数对于“读回”由repr()字符串化的文字值和容器很有用。例如,它可以用于序列化,其格式类似于JSON,但功能比JSON更强大。

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.


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。