Python 中 exec 和 eval 的使用

发布于 2024-10-02 03:26:16 字数 147 浏览 2 评论 0原文

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

谁能给我一些例子,以便我更好地理解这个概念。因为我知道这都是理论。

So I have understood what exec and eval and also compile do. 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

纵性 2024-10-09 03:26:16

我将举一个我使用过 eval 的例子,我认为它是最好的选择。

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

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

我的解决方案是围绕parsed_string=eval('''%s''' % cfg_read_item) 后跟三重双引号版本 ("""%s""") 的 try在这种

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

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

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

I'll give an example in which I have used eval and where I think it was the best choice.

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. 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.

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.

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. 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).

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.

格子衫的從容 2024-10-09 03:26:16

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

The standard library has an instructive example of how to use exec. collections.namedtuple uses it to build a class dynamically.

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)
葬花如无物 2024-10-09 03:26:16

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)

ast uses compile to generate abstract syntax trees from Python source code. These are used by modules such as pyflakes to parse and validate 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)
久而酒知 2024-10-09 03:26:16

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

它们仅在您自己生成代码的情况下才有用,这最终很可能被认为是不好的做法。

如果您正在考虑使用 eval() 来处理数学表达式之类的内容,那么最好在评估输入之前对其进行清理。您永远不知道用户发送的哪种“文本”可能会破坏应用程序本身。

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. You never know what kind of 'text' the user sends in that might screw up the application itself.

抽个烟儿 2024-10-09 03:26:16

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

目标是在每个现有点周围添加新点的同心环,这些环表现为涟漪(就像当您将一块石头扔进池塘时一样)。问题是我希望波纹彼此建设性/破坏性地干扰,所以首先我要遍历并构建一个以每个点为中心的“波纹方程”,并将所有波纹方程加在一起形成一个巨大的数学方程,然后,我将输入原始点,以生成正确的 z 值来分配每个点。

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

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).

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.

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.

云柯 2024-10-09 03:26:16

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

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

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

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. In other languages (Java, C++, etc.) this would be close to impossible to evaluate, but in python it is simple, just:

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.

匿名。 2024-10-09 03:26:16

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

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一些。所以就有了一堆伪代码。

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. 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())

P. S. Sorry, I forgot Python some. So there is a bunch of pseudo-code.

Bonjour°[大白 2024-10-09 03:26:16

这是一个有效的用例。在 python 粘贴中间件(用于 Web 编程)中,当引发异常时,它会在浏览器中创建一个命令行。使用这样的方法可以实现这一点。此外,在 Blender 中,有一个选项可以使用 python 表达式对值进行动画处理,并且可以使用 eval 来实现。

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. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文