【问题标题】:Why is Python's eval() rejecting this multiline string, and how can I fix it?为什么 Python 的 eval() 拒绝这个多行字符串,我该如何解决?
【发布时间】:2012-09-23 18:19:11
【问题描述】:

我正在尝试评估以下制表符缩进的字符串:

'''for index in range(10):
        os.system("echo " + str(index) + "")
'''

我得到,“出现错误:无效语法,第 1 行”

它在抱怨什么?我是否需要缩进以匹配 eval() 语句,或者将其写入字符串文件或临时文件并执行它,或者其他什么?

谢谢,

【问题讨论】:

标签: python python-3.x metaprogramming eval


【解决方案1】:

eval 评估像 5+3 这样的东西

exec 执行for ... 之类的东西

>>> eval("for x in range(3):print x")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    for x in range(3):print x
      ^
SyntaxError: invalid syntax
>>> exec("for x in range(3):print x")
0
1
2
>>> eval('5+3')
8

【讨论】:

【解决方案2】:

要将此类语句与eval 一起使用,您应该先将它们转换为代码对象,使用compile

In [149]: import os

In [150]: cc = compile('''for index in range(10):
    os.system("echo " + str(index) + "")''','<string>','single')

In [154]: eval cc
--------> eval(cc)
0
Out[154]: 0
1
Out[154]: 0
2
Out[154]: 0
3
Out[154]: 0
4

In [159]: cc = compile("2+2", '<string>', 'single')  # works with simple expressions too 

In [160]: eval cc
--------> eval(cc)
Out[160]: 4

【讨论】:

    【解决方案3】:

    我们评估 (eval) 表达式,并执行 (exec) 语句。

    请参阅:Expression Versus Statement

    表达式:计算值的东西。示例:1+2/x
    语句:做某事的一行代码。示例:转到 100

    【讨论】:

      【解决方案4】:

      (在将此类代码投入生产之前,请参阅末尾的默认安全警告!)

      其他答案很好地解释了execeval 之间的区别。

      尽管如此,我发现自己想要像x=1; y=2; x+y 这样的输入而不是强迫人们写:

      def f():
         x = 1
         y = 2
         return x + y
      

      对代码进行字符串操作来构建这种功能是一项冒险的事情。

      我最终使用了以下方法:

      def multiline_eval(expr, context):
          "Evaluate several lines of input, returning the result of the last line"
          tree = ast.parse(expr)
          eval_expr = ast.Expression(tree.body[-1].value)
          exec_expr = ast.Module(tree.body[:-1])
          exec(compile(exec_expr, 'file', 'exec'), context)
          return eval(compile(eval_expr, 'file', 'eval'), context)
      

      这会解析python代码;使用 ast 库重建除最后一行之外的所有内容的 ast;最后一行,执行前者并评估后者。

      安全警告

      这是您必须附加到eval 的强制性安全警告。 由非特权用户提供的Eval'ing 和exec'ing 代码当然是不安全的。在这些情况下,您可能更喜欢使用另一种方法,或者考虑使用 ast.literal_eval。 evalexec 往往不是好主意,除非你真的想为你的用户提供 python 的全部表达能力。

      【讨论】:

        猜你喜欢
        • 2018-09-16
        • 2023-04-11
        • 2020-11-22
        • 1970-01-01
        • 2023-03-18
        • 2021-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多