检查Python中的字符串是否可以通过eval()函数进行求值

6

我知道我可以在 eval 自身中使用 try-except,但我希望在列表推导或 map 中使用它:

[eval(x) if isevaluable(x) else x for x in some_list]

我这么做的原因是: 我从sys.argv获取参数 - 这些参数可以是int\float\内置常量(特别是True,False,None)。我希望以一种简单清晰的方式将它们全部转换。

[注意:safe-eval在这里不是问题(即使它确实被推荐)]


@Ness 我也考虑过这个问题,但是他可能不希望代码实际执行 :) 假设这是在删除文件,并且他想要在列表中得到结果。那么列表对象会有问题,因为 try / except 语句会在该评估实例中删除文件。 - Torxed
@Ness,这是个好主意 - 但我想知道是否有内置的方法(或其他技巧)可以实现。 - alikyos
@Torxed 我猜我们需要问一下 OP 为什么想要过滤可求值元素的列表。在我看来,这似乎是一个 XY 问题。 - Konstantin
1
你实际上想要实现什么?使用eval的可能性非常小。 - jonrsharpe
1
ast.literal_eval(string_value) - Łukasz Rogalski
显示剩余2条评论
2个回答

1
一个显而易见的解决方案,可能对你特定的eval字符串有效或无效。
def isevaluable(s):
    try:
        compile(s, "bogusfile.py", "exec")
        return True
    except:
        return False

这将编译代码并检查语法错误等。它可能无法捕捉到所有逻辑问题,但在将代码传入 eval 执行之前会检查编程问题,以避免可能引起的各种问题。
我考虑了以下做法:
def isevaluable(s):
    try:
        eval(s)
        return True
    except:
        return False

但请记住,您将执行字符串,这可能会使您的结果变得模糊,并将其放入列表中。
例如,如果您的字符串是rm /tmp/cache.txt,则会在isevaluable中给出正面结果,在[eval(x) ...]中给出负面结果,因为它在try语句中被删除了。

在这种情况下,compile()是更好的选择。在任何示例中,它都很可能是最佳选择。


1
首先,如果你的x仅包含字符串、数字、元组、列表、字典、布尔值和None类型的文字,你可以使用ast.literal_eval,这比eval()函数更安全。

ast.literal_eval(node_or_string)

安全地评估表达式节点或包含Python文字或容器显示的Unicode或Latin-1编码字符串。提供的字符串或节点只能由以下Python文字结构组成:字符串、数字、元组、列表、字典、布尔值和None。

此外,你很可能需要自己定义isevaluatable()函数,例如 -
def isevaluatable(s):
    import ast
    try:
        ast.literal_eval(s)
        return True
    except ValueError:
        return False

那么你可以这样做

import ast [ast.literal_eval(x) if isevaluatable(x) else x for x in some_list]

更简单的方法是使函数直接返回所需的值

def myeval(s):
    import ast
    try:
        return ast.literal_eval(s)
    except ValueError:
        return s

然后执行 -
[myeval(x) for x in some_list]

ast.literal_eval 不就相当于 eval(x, {}, {})globalslocals 为空字典)吗? - alikyos
好的 - 我看到了这个链接 Eval真的很危险 - alikyos
我不这么认为,即使没有全局变量和本地变量,你仍然可以运行Python语句对吧?但是如果使用ast.literal_eval(),这是不可能的。 - Anand S Kumar
我没有详细说明我的意图,我的意思是从安全评估的角度来看“等效”。 - alikyos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接