当前位置: 首页 > 面试题库 >

ValueError:使用ast.literal_eval时格式错误的字符串

楚俊逸
2023-03-14
问题内容

众所周知,使用eval()存在潜在的安全风险,因此ast.literal_eval(node_or_string)提倡使用

但是在python 2.7中,ValueError: malformed string运行此示例时会返回:

>>> ast.literal_eval("4 + 9")

而在python 3.3中,此示例按预期工作:

>>> ast.literal_eval('4+9')
13

为什么它在python 3而不是python 2上运行?如何在不使用高风险eval()函数的情况下在python 2.7中进行修复?


问题答案:

这在Python
2上不起作用的原因在于它的实现literal_eval。当righth操作数为复数时,原始实现只对加法和减法执行数字求值。在语法上,必须将复数表示为文字,这在语法上是必需的。

这个改变在Python
3,以便它支持任何类型的有效的数字表达的是对加法和减法的任一侧。但是,的使用literal_eval仍然仅限于加法和减法。

这主要是因为literal_eval应该是一个将单个 常量
文字(表示为字符串)转换为Python对象的函数。有点像repr简单内置类型的倒退。不包括实际的表达式评估,并且它与Python
3一起使用的事实只是其实现的一个不错的副作用。

为了评估实际的表达式而不必使用eval(我们不想使用),我们可以编写自己的基于AST的表达式评估算法。这非常简单,尤其是对于数字的简单算术运算(例如,构建自己的计算器等)时。我们只需将字符串解析为AST,然后通过查看不同的节点类型并应用正确的操作来评估结果树。

像这样:

import ast, operator

binOps = {
    ast.Add: operator.add,
    ast.Sub: operator.sub,
    ast.Mult: operator.mul,
    ast.Div: operator.div,
    ast.Mod: operator.mod
}

def arithmeticEval (s):
    node = ast.parse(s, mode='eval')

    def _eval(node):
        if isinstance(node, ast.Expression):
            return _eval(node.body)
        elif isinstance(node, ast.Str):
            return node.s
        elif isinstance(node, ast.Num):
            return node.n
        elif isinstance(node, ast.BinOp):
            return binOps[type(node.op)](_eval(node.left), _eval(node.right))
        else:
            raise Exception('Unsupported type {}'.format(node))

    return _eval(node.body)

如您所见,此实现非常简单。当然,它还不支持指数运算和一些一元节点之类的更复杂的东西,但是添加它并不难。而且效果很好:

>>> arithmeticEval('4+2')
6
>>> arithmeticEval('4*1+2*6/3')
8

您甚至可以在以后介绍更复杂的内容(例如,函数调用,例如sin())。



 类似资料:
  • 问题内容: 使用uCanaccess检索保存在桌面中的数据库时出现错误。 我的代码如下: 导入java.util.Scanner; 导入java.sql。*; 公共类dbTest1 { } 我将很乐意为您解决此错误提供任何建议。 谢谢,文斯 问题答案: 好吧,首先,导入您的库(lib文件夹中的jar文件)。http://sourceforge.net/projects/ucanaccess/fil

  • 问题内容: 我对这部分代码有疑问,我正在尝试在预订表中插入一条记录。我试图输入的值是(6,3,3,20/06/2018 00:00:00,400,2800.00,True,560.00) 我收到的错误如下, “从字符串转换日期和/或时间时转换失败。” 我已尽力研究此问题,但我不知道如何解决此问题。任何帮助表示赞赏。 问题答案: Okey,您的代码有一些问题。我将尝试按顺序解释所有这些内容。 首先,

  • 编辑:感谢Preetam Kumar,这个问题已经解决,但错误现在在其他地方。当我再次尝试解组我的xml文件时,我收到这个错误,告诉我找不到元素: 然而,我给了xml文件到模式的正确路径,但是它似乎没有使用它...我不明白。 注意:我知道模式和xml标记在下面的示例中不完全匹配,我已经在我的文件中纠正了它。 最近,我不得不使用JAXB java库将一些XML文件解析为java对象。 我制作了一个X

  • 问题内容: 我收到以下错误: 第一个字段是格式。 有任何想法吗? 谢谢。 问题答案: 当您将字符串值插入日期列时,则需要在使用函数期间将其转换为日期。使用此功能时,您将提供字符串的格式。 功能格式: 因此,您的查询将如下所示: 参见带有演示的SQL Fiddle

  • 无法打印出格式错误弹出的结果。 尝试在没有getWaitingTime()和%-20d(最后一个)的情况下执行,它可以工作。 尝试执行1,并用getWaitingTime()替换seqNo,它可以工作。 不确定是什么错误。 它调用toString方法的部分。它从servicelist被称为。 至于错误是: JAVAutil。MissingFormatArgumentException:邮局的格式说

  • 问题内容: 我正在尝试学习Python(更具体地讲3),并且遇到此错误: 我用谷歌搜索,发现需要指定数字: 而且不像该教程(来自lynda.com)实际上说的那样: 以下教程即时消息具有Python 3.1,即时消息使用3.2,而我读到的有关此错误的信息是,此错误仅发生在<3.1(3.0)中。他们在3.2中撤消了此操作,还是我做错了什么? 另外,说慢点;)从字面上看,这是我学习Python的第一个