Python 的 eval() 有什么作用?
- 2024-12-06 08:40:00
- admin 原创
- 99
问题描述:
我正在阅读的有关 Python 的书反复显示如下代码eval(input('blah'))
。
这究竟如何修改调用的结果input
?
另请参阅: 为什么使用“eval”是一种不好的做法?以了解使用或不受信任的输入(即:任何部分受用户控制而不是程序控制的事物)所产生的严重安全风险。eval
`exec`
另请参阅: 如何在纯 Python 中沙盒化 Python?简而言之,正确地做到这一点总是比选择合适的工具而不是eval
或更难exec
。
请参阅使用 python 的 eval() 与 ast.literal_eval()来了解可能更安全的技术。
请参阅如何在 Python 3 中使用 raw_input?以了解书籍可能包含此类代码的背景知识,或者 OP 最初可能期望结果input
不需要进一步处理的原因。
解决方案 1:
eval 函数让 Python 程序在其内部运行 Python 代码。
eval 示例(交互式 shell):
>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1
解决方案 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__'}
模块中的某些函数肯定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
可以安全地使用它来获得巨大的价值。
注意:
这些的另一个很酷的地方kwargs
是,您可以开始使用简写来编写代码。假设您使用eval作为管道的一部分来执行一些导入的文本。文本不需要有确切的代码,它可以遵循一些模板文件格式,并且仍然可以执行您想要的任何内容。例如:
>>> from os import cpu_count
>>> eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]
解决方案 4:
在 Python 2.x 中input(...)
相当于eval(raw_input(...))
,在 Python 3.x 中raw_input
被重命名为input
,我怀疑这会导致您混淆(您可能正在查看 Python 2.x 中的文档input
)。此外,eval(input(...))
在 Python 3.x 中可以正常工作,但在 Python 2 中会引发TypeError
。
在这种情况下,eval
用于将返回的字符串强制转换input
为表达式并进行解释。通常这被认为是不好的做法。
解决方案 5:
如果您想将评估字符串限制为简单文字,另一个选择是使用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 文字结构组成:字符串、字节、数字、元组、列表、字典、集合、布尔值和 None。
这可用于安全地评估包含来自不受信任来源的 Python 值的字符串,而无需自己解析这些值。它无法评估任意复杂的表达式,例如涉及运算符或索引的表达式。
至于为什么它如此有限,来自邮件列表:
允许使用文字的运算符表达式是可能的,但比当前实现复杂得多。简单的实现并不安全:您可以毫不费力地引发基本上不受限制的 CPU 和内存使用(尝试“999”或“[None] 9*9”)。
至于实用性,此函数可用于“读回”由 repr() 字符串化的文字值和容器。例如,这可以用于以与 JSON 类似但功能更强大的格式进行序列化。
解决方案 6:
eval()
,顾名思义,对传递的参数进行求值。
raw_input()
现在已input()
包含在 Python 3.x 版本中。因此,最常见的使用示例是使用它来提供Python 2.x 版本中提供的eval()
功能。input()
raw_input将用户输入的数据以字符串形式返回,而input 则评估输入数据的值并返回它。
eval(input("bla bla"))
因此复制了 2.x 中的功能input()
,即评估用户输入的数据。
简而言之:eval()
评估传递给它的参数并eval('1 + 1')
返回 2。
解决方案 7:
这也许是阅读一行并解释它的一个误导性例子。
尝试eval(input())
并输入"1+1"
- 这应该会打印2
。Eval 评估表达式。
解决方案 8:
eval()
将传递的字符串作为 Python 表达式进行求值并返回结果。例如,eval("1 + 1")
解释并执行表达式"1 + 1"
并返回结果 (2)。
您可能感到困惑的一个原因是,您引用的代码涉及间接层。内部函数调用(输入)首先执行,因此用户会看到“blah”提示。让我们假设他们回答“1 + 1”(为清楚起见添加了引号,运行程序时不要输入引号),输入函数返回该字符串,然后将其传递给外部函数(eval),该函数解释该字符串并返回结果(2)。
在这里阅读有关 eval 的更多信息。
解决方案 9:
的一个有用应用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!'}
解决方案 10:
如果用户输入数字值,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()
。
>>> float(input('Enter a number: '))
Enter a number: 3.14
3.14
解决方案 11:
eval() 函数接受三个参数来计算并返回值。
语法: eval(expression, globals, locals)
expression #python3 表达式的字符串
globals (可选) #dictionary
locals (可选) #dictionary
您经常使用的常见用例是
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'>
解决方案 12:
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
^
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件