18

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

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

我得到,“有一个错误:无效的语法,第 1 行”

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

谢谢,

4

4 回答 4

29

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
于 2012-10-02T20:47:20.417 回答
15

要使用此类语句,您应该首先使用compileeval将它们转换为代码对象:

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
于 2012-10-02T20:52:10.783 回答
6

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

请参阅:表达式与语句

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

于 2012-10-02T20:53:28.447 回答
6

(在将这样的代码投入生产之前,请参阅最后的默认安全警告!)

其他答案很好地解释了exec和之间的区别eval

尽管如此,我发现自己想要接受输入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 和'ing 代码当然是不安全的。exec在这些情况下,您可能更喜欢使用另一种方法,或者考虑使用 ast.literal_eval。eval并且exec往往是坏主意,除非你真的想给你的用户充分的 python 表达能力。

于 2017-01-04T20:25:29.130 回答