在我正在阅读Python的书中,它继续使用代码 eval(input('blah'))
我阅读了文档,我理解它,但我仍然没有看到它如何改变input()
功能.
它有什么作用?谁能解释一下?
BYS*_*YS2 248
eval函数允许Python程序在其自身内部运行Python代码.
eval示例(交互式shell):
>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1
Run Code Online (Sandbox Code Playgroud)
Cof*_*ain 150
eval()
将字符串解释为代码.这么多人警告你使用它的原因是因为用户可以使用它作为在计算机上运行代码的选项.如果您已导入eval(input())
并os
导入,则可以键入一个人input()
os.system('rm -R *')
将删除主目录中的所有文件.(假设你有一个unix系统).使用eval()
是一个安全漏洞.如果您需要将字符串转换为其他格式,请尝试使用这样做的内容,例如int()
.
Grr*_*Grr 51
这里有很多好的答案,但没有一个描述在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__'}
Run Code Online (Sandbox Code Playgroud)
builtins
模块中肯定有一些方法可以对系统造成重大损害.但是有可能阻止任何我们不想要的东西.我们来举个例子吧.假设我们要构建一个列表来表示系统上可用核心的域.对我来说,我有8个核心,所以我想要一个列表[1, 8]
.
>>>from os import cpu_count
>>>eval('[1, cpu_count()]')
[1, 8]
Run Code Online (Sandbox Code Playgroud)
同样所有__builtins__
都可用.
>>>eval('abs(-1)')
1
Run Code Online (Sandbox Code Playgroud)
好.因此,我们看到一个我们想要暴露的方法,以及一个我们不想暴露的方法(很多可能更复杂的方法)的例子.所以让我们阻止一切.
>>>eval('[1, cpu_count()]', {'__builtins__':None}, {})
TypeError: 'NoneType' object is not subscriptable
Run Code Online (Sandbox Code Playgroud)
我们已经有效地阻止了所有__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
Run Code Online (Sandbox Code Playgroud)
现在我们有cpu_count方法可用,同时仍然阻止我们不想要的一切.在我看来,这是超级强大的,显然从其他答案的范围不是一个常见的实现.对于这样的东西有很多用途,只要处理得当,我个人觉得cpu_count
可以安全地使用它.
NB
其他一些很酷的事情eval
是你可以开始使用速记代码.假设您使用eval作为管道的一部分来执行某些导入的文本.文本不需要具有确切的代码,它可以遵循一些模板文件格式,并且仍然执行您想要的任何内容.例如:
>>>from os import cpu_count
>>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]
Run Code Online (Sandbox Code Playgroud)
zee*_*kay 29
在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中提升.
在这种情况下eval
,用于强制从input
表达式返回的字符串并进行解释.通常这被认为是不好的做法.
的有用应用之一eval()
是从字符串评估python表达式。例如从字典的文件字符串表示形式加载:
running_params = {"Greeting":"Hello "}
fout = open("params.dat",'w')
fout.write(repr(running_params))
fout.close()
Run Code Online (Sandbox Code Playgroud)
将其读取为变量并进行编辑:
fin = open("params.dat",'r')
diction=eval(fin.read())
diction["Greeting"]+="world"
fin.close()
print diction
Run Code Online (Sandbox Code Playgroud)
输出:
{'Greeting': 'Hello world'}
Run Code Online (Sandbox Code Playgroud)
eval()
顾名思义,评估传递的参数.
raw_input()
现在input()
是python 3.x版本.因此,最常见的使用示例eval()
是它用于提供input()
2.x版本的python中提供的功能.raw_input将用户输入的数据作为字符串返回,而input输入评估输入的数据的值并将其返回.
eval(input("bla bla"))
因此,复制input()
2.x中的功能,即评估用户输入的数据.
简而言之:eval()
评估传递给它的参数,因此eval('1 + 1')
返回2.
小智 5
我回答这个问题迟到了,但似乎没有人对这个问题给出明确的答案。
如果用户输入一个数值,input()
将返回一个字符串。
>>> input('Enter a number: ')
Enter a number: 3
>>> '3'
>>> input('Enter a number: ')
Enter a number: 1+1
'1+1'
Run Code Online (Sandbox Code Playgroud)
因此,eval()
将评估作为字符串的返回值(或表达式)并返回整数/浮点数。
>>> eval(input('Enter a number: '))
Enter a number: 1+1
2
>>>
>>> eval(input('Enter a number: '))
Enter a number: 3.14
3.14
Run Code Online (Sandbox Code Playgroud)
当然,这是一种不好的做法。在这种情况下应该使用int()
orfloat()
代替eval()
。
>>> float(input('Enter a number: '))
Enter a number: 3.14
3.14
Run Code Online (Sandbox Code Playgroud)
如果要将评估字符串限制为简单文字,另一种选择是使用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}
Run Code Online (Sandbox Code Playgroud)
从文档:
安全地计算包含 Python 文字或容器显示的表达式节点或字符串。提供的字符串或节点只能由以下 Python 文字结构组成:字符串、字节、数字、元组、列表、字典、集合、布尔值和无。
这可用于安全地评估包含来自不受信任来源的 Python 值的字符串,而无需自己解析这些值。它不能评估任意复杂的表达式,例如涉及运算符或索引。
至于为什么如此有限,来自邮件列表:
允许带有文字的运算符表达式是可能的,但比当前的实现要复杂得多。一个简单的实现是不安全的:您可以毫不费力地诱导基本上无限制的 CPU 和内存使用(尝试“9**9**9”或“[None] * 9**9”)。
至于有用性,此函数可用于“读回”由 repr() 字符串化的文字值和容器。例如,这可以用于以类似于 JSON 但比 JSON 更强大的格式进行序列化。