简体   繁体   English

在Python中使用exec和eval

[英]Use of exec and eval in Python

So I have understood what exec and eval and also compile do. 所以我已经理解了execeval以及compile But why would I need to use them? 但为什么我需要使用它们呢? I am being unclear on the usage scenario. 我对使用场景不清楚。

Can anyone give me some examples so that I can better appreciate the concept. 任何人都可以给我一些例子,以便我能更好地欣赏这个概念。 Cause right I know it is all theory. 因为我知道这都是理论。

I'll give an example in which I have used eval and where I think it was the best choice. 我举一个例子,其中我使用了eval ,我觉得它是最好的选择。

I was writing a simple software testing utility ... something to test whether student exercises were conforming to the assignment requirements. 我正在编写一个简单的软件测试实用程序......用于测试学生练习是否符合作业要求。 The goal was to provide a way for a simple configuration file to serve as a test specification (to get around a "chicken-and-egg" issue of using a programming language to describe/document/implement the test cases for elementary programming assignments). 目标是为简单的配置文件提供一种方法作为测试规范(解决使用编程语言描述/记录/实现基本编程分配的测试用例的“鸡与鸡蛋”问题) 。

I based my harness on the ConfigParser in the standard libraries. 我将我的工具基于标准库中的ConfigParser。 However, I did want the ability to represent arbitrary Python strings (including interpolations of \\n, \\t, and especially any interpolated hex encoded ASCII characters in the values read therefrom. 但是,我确实希望能够表示任意Python字符串(包括\\ n,\\ t的插值,尤其是从中读取的值中的任何插值的十六进制编码的ASCII字符。

My solution was a try around an parsed_string=eval('''%s''' % cfg_read_item) followed by a try of the triple double-quoted version ("""%s""") of the same. 我的解决方案是try parsed_string=eval('''%s''' % cfg_read_item)一个parsed_string=eval('''%s''' % cfg_read_item)然后try三重双引号版本(“”“%s”“”)。

This is a case where the alternative would have been to write (or find a pre-written) Python language parser and figure out how to include and adapt it to my program. 这种情况下,替代方案可能是编写(或找到预先编写的)Python语言解析器,并弄清楚如何将其包含并调整到我的程序中。 The risks are minimal (I'm not worried that student submitted code is going to trick my parser, break out if its jail, delete all my files, send my credit card numbers to Romania and so on)* 风险很小(我不担心学生提交的代码会欺骗我的解析器,如果它的监狱爆发,删除我的所有文件,将我的信用卡号发送到罗马尼亚等等)*

*(In part because I was testing them under Linux from an untrusted headless user account). *(部分原因是我在Linux下从不受信任的无头用户帐户测试它们)。

As here others have said, there are other use cases where you're building code from a template based on input data and need to execute that code (meta programming). 正如其他人所说,还有其他一些用例,你根据输入数据从模板构建代码,并需要执行该代码(元编程)。 You should always be able to accomplish those tasks in another way. 您应始终能够以其他方式完成这些任务。 However, whenever that alternative entails coding effort that approaches writing a general programming language parser/compiler/interpreter .... then eval may be the better approach. 但是,无论何时该替代方案都需要编写一种编写通用编程语言解析器/编译器/解释器的编写工作....那么eval可能是更好的方法。

The standard library has an instructive example of how to use exec . 标准库有一个如何使用exec的指导性示例。 collections.namedtuple uses it to build a class dynamically. 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 uses compile to generate abstract syntax trees from Python source code. ast使用compile从Python源代码生成抽象语法树。 These are used by modules such as pyflakes to parse and validate 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)

I think I have a valid use. 我想我有一个有效的用途。 I am using Python 3.2.1 inside Blender 2.6.4 to modify a set of points with x,y coordinates (in the z-plane). 我在Blender 2.6.4中使用Python 3.2.1来修改一组带有x,y坐标的点(在z平面中)。

The goal is to add concentric rings of new points around each existing point, with the rings behaving as ripples, (like when you drop a stone in a pond). 目标是在每个现有点周围添加同心环的新点,环表现为涟漪(就像当你在池塘里扔石头时)。 The catch is that I want the ripples to constructively/destructively interfere with one another, so first I'm going through and constructing a 'ripple equation' centered at each point, and summing all the ripple equations together into one gigantic mathematical equation, which I will then feed the original points into in order to generate the correct z-value to assign each one to. 问题在于我希望涟漪能够建设性地/破坏性地相互干扰,所以首先我要经历并构建一个以每个点为中心的“波纹方程”,并将所有波纹方程式汇总成一个巨大的数学方程式,然后,我将原始点馈入,以生成正确的z值,以指定每个点。

My plan is to append each additional term in the equation to the previous as a string, and then use eval() to calculate the z-value for the new set of points. 我的计划是将方程中的每个附加项附加到前一个字符串,然后使用eval()计算新点集的z值。

You don't need to use them, and in my opinion you should avoid them. 不需要使用它们,在我看来你应该避免使用它们。

They are only useful in cases where you are generating the code itself, which in the end is going to most likely be considered bad practice. 它们仅在您自己生成代码的情况下才有用,最终这些代码很可能被视为不良实践。

If you are considering using eval() for things like mathematical expressions, you would be better sanitizing the input before evaluating it. 如果您正在考虑对数学表达式之类的东西使用eval(),那么在评估输入之前,最好先对输入进行清理。 You never know what kind of 'text' the user sends in that might screw up the application itself. 你永远不知道用户发送的那种“文本”可能搞砸了应用程序本身。

Are you just asking for an example? 你只想问一个例子吗? You could write a simple app that reads from standard in and allows the user to input various expressions, like (4*2)/8 - 1 . 您可以编写一个从标准读取的简单应用程序,并允许用户输入各种表达式,如(4*2)/8 - 1 In other languages (Java, C++, etc.) this would be close to impossible to evaluate, but in python it is simple, just: 在其他语言(Java,C ++等)中,这几乎无法评估,但在python中它很简单,只需:

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

That being said, unless you are careful, using these things can be very dangerous as they (essentially)allow the user a huge amount of access. 话虽这么说,除非你小心,使用这些东西可能非常危险,因为它们(基本上)允许用户进行大量访问。

This is used in meta-programming (when the program writes itself). 这用于元编程(当程序自行编写时)。 For example, you have animals of different species, which are described with different classes: Lion, Tiger, Horse, Donkey. 例如,你有不同种类的动物,用不同的类别描述:狮子,老虎,马,驴。 And you want to simulate crossbreeding between them, for exampe, between Lion and Tiger. 并且你想模拟它们之间的杂交,例如Lion和Tiger之间的杂交。 When you write the program, you can not determine how the user will cross the animals, but you can create new classes of animals on the fly: 当您编写程序时,您无法确定用户如何穿越动物,但您可以动态创建新的动物类:

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 Sorry, I forgot Python some. PS对不起,我忘记了一些Python。 So there is a bunch of pseudo-code. 所以有一堆伪代码。

Here's a valid use case. 这是一个有效的用例。 In the python paste middleware (for web programming) when an exception is raised it creates a command line within the browser. 在python paste中间件(用于web编程)中,当引发异常时,它会在浏览器中创建一个命令行。 This works be using methods like these. 这可以使用这些方法。 Also, in Blender there is an option to animate values using python expressions and this works using eval. 此外,在Blender中有一个使用python表达式为值设置动画的选项,这可以使用eval。

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

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