问题:Python的eval()有什么作用?
在我用Python阅读的书中,它一直在使用代码 eval(input('blah'))
我阅读了文档,但我理解了它,但仍然看不到它如何更改input()
功能。
它有什么作用?有人可以解释吗?
回答 0
eval函数允许Python程序在其内部运行Python代码。
评估示例(交互式外壳):
>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1
回答 1
eval()
将字符串解释为代码。之所以有如此多的人警告您使用此功能,是因为用户可以将其用作在计算机上运行代码的选项。如果你有eval(input())
和os
进口的,一个人可以键入input()
os.system('rm -R *')
这将删除你的家目录中的所有文件。(假设您有一个Unix系统)。使用eval()
是一个安全漏洞。如果您需要将字符串转换为其他格式,请尝试使用可实现此目的的东西int()
。
回答 2
这里有很多很好的答案,但没有一个描述在eval()
它globals
和locals
kwargs 的上下文中的使用,即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]
回答 3
在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中可以提高a 。
在这种情况下eval
,用于强制将返回的字符串input
转换为表达式并进行解释。通常,这被认为是不良做法。
回答 4
也许是读一行并解释它的一个令人误解的例子。
尝试eval(input())
输入"1+1"
-这应该打印出来2
。Eval计算表达式。
回答 5
eval()
将传递的字符串评估为Python表达式并返回结果。例如,eval("1 + 1")
解释并执行表达式"1 + 1"
并返回结果(2)。
您可能会感到困惑的一个原因是,您引用的代码涉及一种间接级别。内部函数调用(输入)首先执行,因此用户看到“ blah”提示。假设它们以“ 1 +1”响应(为清楚起见添加了引号,请在运行程序时不要键入它们),输入函数返回该字符串,然后将其传递给外部函数(eval),该函数解释该字符串并返回结果(2)。
在此处阅读有关eval的更多信息。
回答 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。
回答 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'}
回答 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
回答 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更强大。