Python的eval()做什么?

2024-04-19 20:23:14 发布

您现在位置:Python中文网/ 问答频道 /正文

在我正在读的关于Python的书中,它一直在使用代码eval(input('blah'))

我阅读了文档,并且理解了它,但是我仍然看不到它如何更改input()函数。

它是做什么的?有人能解释吗?


Tags: 函数代码文档inputevalblah
3条回答

eval函数允许Python程序在其内部运行Python代码。

评估示例(交互式shell):

>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1

eval()将字符串解释为代码。之所以有这么多人警告您使用它,是因为用户可以使用它作为在计算机上运行代码的选项。如果导入了eval(input())os,用户可以键入input()os.system('rm -R *'),删除主目录中的所有文件。(假设您有一个unix系统)。使用eval()是一个安全漏洞。如果需要将字符串转换为其他格式,请尝试使用这样的格式,如int()

这里有很多好的答案,但是没有一个能描述eval()globalslocalskwargs的上下文中的用法,即eval(expression, globals=None, locals=None)(参见文档中的evalhere)。

这些可用于限制通过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可以安全地使用到很大的价值。

N.B.

这些kwargs还有一点很酷,那就是您可以开始对代码使用速记。假设您使用eval作为管道的一部分来执行一些导入的文本。文本不需要有精确的代码,它可以遵循一些模板文件格式,仍然执行任何您想要的。例如:

>>>from os import cpu_count
>>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]

相关问题 更多 >