繁体   English   中英

在Python中使用exec和eval

[英]Use of exec and eval in Python

所以我已经理解了execeval以及compile 但为什么我需要使用它们呢? 我对使用场景不清楚。

任何人都可以给我一些例子,以便我能更好地欣赏这个概念。 因为我知道这都是理论。

我举一个例子,其中我使用了eval ,我觉得它是最好的选择。

我正在编写一个简单的软件测试实用程序......用于测试学生练习是否符合作业要求。 目标是为简单的配置文件提供一种方法作为测试规范(解决使用编程语言描述/记录/实现基本编程分配的测试用例的“鸡与鸡蛋”问题) 。

我将我的工具基于标准库中的ConfigParser。 但是,我确实希望能够表示任意Python字符串(包括\\ n,\\ t的插值,尤其是从中读取的值中的任何插值的十六进制编码的ASCII字符。

我的解决方案是try parsed_string=eval('''%s''' % cfg_read_item)一个parsed_string=eval('''%s''' % cfg_read_item)然后try三重双引号版本(“”“%s”“”)。

这种情况下,替代方案可能是编写(或找到预先编写的)Python语言解析器,并弄清楚如何将其包含并调整到我的程序中。 风险很小(我不担心学生提交的代码会欺骗我的解析器,如果它的监狱爆发,删除我的所有文件,将我的信用卡号发送到罗马尼亚等等)*

*(部分原因是我在Linux下从不受信任的无头用户帐户测试它们)。

正如其他人所说,还有其他一些用例,你根据输入数据从模板构建代码,并需要执行该代码(元编程)。 您应始终能够以其他方式完成这些任务。 但是,无论何时该替代方案都需要编写一种编写通用编程语言解析器/编译器/解释器的编写工作....那么eval可能是更好的方法。

标准库有一个如何使用exec的指导性示例。 collections.namedtuple使用它动态构建一个类。

template = '''class %(typename)s(tuple):
    '%(typename)s(%(argtxt)s)' \n
    __slots__ = () \n
    _fields = %(field_names)r \n
    def __new__(_cls, %(argtxt)s):
        'Create new instance of %(typename)s(%(argtxt)s)'
        return _tuple.__new__(_cls, (%(argtxt)s)) \n
    ...'''

   namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
                     OrderedDict=OrderedDict, _property=property, _tuple=tuple)
   try:
       exec template in namespace
   except SyntaxError, e:
       raise SyntaxError(e.message + ':\n' + template)

ast使用compile从Python源代码生成抽象语法树。 这些由pyflakes等模块用于解析和验证Python。

def parse(expr, filename='<unknown>', mode='exec'):
    """
    Parse an expression into an AST node.
    Equivalent to compile(expr, filename, mode, PyCF_ONLY_AST).
    """
    return compile(expr, filename, mode, PyCF_ONLY_AST)

我想我有一个有效的用途。 我在Blender 2.6.4中使用Python 3.2.1来修改一组带有x,y坐标的点(在z平面中)。

目标是在每个现有点周围添加同心环的新点,环表现为涟漪(就像当你在池塘里扔石头时)。 问题在于我希望涟漪能够建设性地/破坏性地相互干扰,所以首先我要经历并构建一个以每个点为中心的“波纹方程”,并将所有波纹方程式汇总成一个巨大的数学方程式,然后,我将原始点馈入,以生成正确的z值,以指定每个点。

我的计划是将方程中的每个附加项附加到前一个字符串,然后使用eval()计算新点集的z值。

不需要使用它们,在我看来你应该避免使用它们。

它们仅在您自己生成代码的情况下才有用,最终这些代码很可能被视为不良实践。

如果您正在考虑对数学表达式之类的东西使用eval(),那么在评估输入之前,最好先对输入进行清理。 你永远不知道用户发送的那种“文本”可能搞砸了应用程序本身。

你只想问一个例子吗? 您可以编写一个从标准读取的简单应用程序,并允许用户输入各种表达式,如(4*2)/8 - 1 在其他语言(Java,C ++等)中,这几乎无法评估,但在python中它很简单,只需:

eval((4*2)/8 - 1)

话虽这么说,除非你小心,使用这些东西可能非常危险,因为它们(基本上)允许用户进行大量访问。

这用于元编程(当程序自行编写时)。 例如,你有不同种类的动物,用不同的类别描述:狮子,老虎,马,驴。 并且你想模拟它们之间的杂交,例如Lion和Tiger之间的杂交。 当您编写程序时,您无法确定用户如何穿越动物,但您可以动态创建新的动物类:

new_class_name = boy.class.to_str() + girl.class.to_str()
eval("class " + new_class_name + " extends " + boy.class.to_str() + ", " + girl.class.to_str())

PS对不起,我忘记了一些Python。 所以有一堆伪代码。

这是一个有效的用例。 在python paste中间件(用于web编程)中,当引发异常时,它会在浏览器中创建一个命令行。 这可以使用这些方法。 此外,在Blender中有一个使用python表达式为值设置动画的选项,这可以使用eval。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM