Python的eval()是做什么的?
在我正在阅读Python的书中,它一直使用代码eval(input('blah'))
我读了文档,我明白了,但我仍然没有看到它如何改变input()
函数。
它有什么作用? 有人可以解释吗?
eval函数让python程序自己运行python代码。
eval示例(交互式shell):
>>> x = 1 >>> eval('x + 1') 2 >>> eval('x') 1
eval()
将string解释为代码。 为什么有这么多人警告你使用它的原因是因为用户可以使用它作为在计算机上运行代码的一个选项。 如果你有eval(input())
和os
导入,一个人可以input到input()
os.system('rm -R *')
,这将删除你的主目录中的所有文件。 (假设你有一个unix系统)。 使用eval()
是一个安全漏洞。 如果您需要将string转换为其他格式,请尝试使用这样的事情,如int()
。
在Python 2.x input(...)
相当于eval(raw_input(...))
,在Python 3.x raw_input
被重命名input
,我怀疑导致你的困惑(你可能正在看文档input
Python 2.x)。 另外, eval(input(...))
在Python 3.x中可以正常工作,但会在Python 2中TypeError
。
在这种情况下, eval
用于强制从input
返回到expression式和解释的string。 通常这被认为是不好的做法。
Eval()将传递的string评估为Pythonexpression式并返回结果。 例如,eval(“1 + 1”)解释并执行expression式“1 + 1”并返回结果(2)。
你可能会感到困惑的一个原因是因为你引用的代码涉及到一个间接的级别。 内部函数调用(input)首先执行,以便用户看到“等”提示。 让我们想象他们用“1 + 1”(为了清晰起见添加了引号,不要在运行程序时input它们)input函数返回该string,然后传递给解释string的外部函数(eval)返回结果(2)。
阅读更多关于eval的信息 。
eval()的有用应用之一是从string中评估pythonexpression式。 例如从字典的文件string表示加载:
running_params = {"Greeting":"Hello "} fout = open("params.dat",'w') fout.write(repr(running_params)) fout.close()
将其作为variables读出并编辑它:
fin = open("params.dat",'r') diction=eval(fin.read()) diction["Greeting"]+="world" fin.close() print diction
输出:
{'问候':'Hello world'}
也许是读一条线并解释它的误导性例子。
尝试eval(input())
并键入"1+1"
– 这应该打印2
。 评估expression式。
eval()
,顾名思义,评估传递的参数。
input()
现在是python 3.x版本中的raw_input()
。 所以使用eval()
的最常见的例子就是用它来提供在2.x版本的python中提供的input()
的function。 raw_input以stringforms返回用户input的数据,而input则评估input的数据的值并将其返回。
eval(input("bla bla"))
因此在2.x中复制了input()
的function,即评估用户input的数据。
总之:eval()计算传递给它的参数,因此eval('1 + 1')返回2。
Lot在这里是很好的答案,但没有一个描述在globals=
和locals=
kwargs的情况下使用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
模块中肯定有方法可以对系统造成严重的损害。 但是可以阻止任何事情和我们不想要的东西。 我们来举个例子。 假设我们要构build一个列表来表示系统上可用内核的一个域。 对我来说,我有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作为pipe道的一部分来执行一些导入的文本。 文本不需要有确切的代码,它可以遵循一些模板文件格式,并且仍然执行任何你想要的。 例如:
>>>from os import cpu_count >>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()}) [1, 8]
eval()
使用一个string,其中包含整数,一个math方程式(string中的任何内容都被视为文本,所以整数意味着数字就像文本一样),所以如果需要帮助的话。