在Python中使用exec和eval

时间:2010-11-11 18:51:33

标签: python eval exec

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

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

8 个答案:

答案 0 :(得分:5)

我将举例说明我使用eval并认为这是最佳选择。

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

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

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

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

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

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

答案 1 :(得分:4)

标准库有一个如何使用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)

答案 2 :(得分:3)

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)

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:1)

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

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

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

答案 5 :(得分:0)

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

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

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

答案 6 :(得分:0)

这用于元编程(当程序自行编写时)。例如,你有不同种类的动物,用不同的类别描述:狮子,老虎,马,驴。并且你想模拟它们之间的杂交,例如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())

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

答案 7 :(得分:0)

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