Answers:
eval函数允许Python程序在其内部运行Python代码。
评估示例(交互式外壳):
>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1
eval()
也可以用来执行高度动态的代码,但是在使用它之前,您应该使自己充分了解安全和性能风险。
eval
,也不会使用eval
。
eval
,除了不安全之外,无法像Codepad一样运行整个程序,因为它只能计算单个表达式。
eval()
将字符串解释为代码。之所以有如此多的人警告您使用此功能,是因为用户可以将其用作在计算机上运行代码的选项。如果你有eval(input())
和os
进口的,一个人可以键入input()
os.system('rm -R *')
这将删除你的家目录中的所有文件。(假设您有一个Unix系统)。使用eval()
是一个安全漏洞。如果您需要将字符串转换为其他格式,请尝试使用可实现此目的的东西int()
。
eval
with input()
是一个安全漏洞。不要放入input()
eval语句,这样就可以了。
eval
在许多情况下,安全问题。
input
通常是从控制台获取数据,因此用户可以直接退出程序并键入rm -R *
...
这里有很多很好的答案,但没有一个描述在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]
在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
转换为表达式并进行解释。通常,这被认为是不良做法。
input
意味着raw_input
2.x中做了什么。
的有用应用之一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'}
eval
问题?
我迟迟未回答这个问题,但是似乎没人能给出明确的答案。
如果用户输入数字值,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
如果要将评估字符串限制为简单文字,则可以使用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更强大。
ast.literal_eval
不支持运算符,与您的'1+1'
示例相反。尽管如此,它确实支持列表,数字,字符串等,因此是常见eval
用例的不错选择。