如何正确解释单行python代码?

时间:2014-05-09 21:54:26

标签: python python-3.x command-line eval interpreter

我需要执行一行由用户输入的python代码。 如果它是一个语句我想执行它,但如果它是一个表达式,我希望返回结果并用它做一些奇特的东西。 问题是python有两个不同的功能,即execeval

目前我只是尝试评估用户输入的字符串。 如果这引发了一个SyntaxError,这可能表明该字符串是一个语句,所以我尝试执行它。

try:
    result = eval(command, scope)
except SyntaxError:
    # Probably command is a statement, not an expression
    try:
        exec(command, scope)
    except Exception as e:
        return command + ' : ' + str(e)
except Exception as e:
    return command + ' : ' + str(e)
else:
    pass # Some fancy stuff

这感觉相当hacky。是否有更整洁,更蟒蛇的方式来做到这一点?

3 个答案:

答案 0 :(得分:4)

虽然我认为你现有的代码可能是合理的Pythonic(根据它的原则#34;更容易请求宽恕而不是许可")我怀疑最好的替代方法是使用{{ 3}}模块检查字符串中的代码:

tree = ast.parse(some_input_string)
if len(tree.body) == 1 and isinstance(tree.body[0], ast.Expr):
    result = eval(some_input_string, scope)
else:
    exec(some_input_string, scope)
    result = None

请注意,一些常见的陈述实际上是"表达式陈述"。因此,像'do_stuff("args")'这样的输入字符串将使用上面代码的eval分支,而不是exec分支。我不认为这会产生任何不良后果,但你永远不会知道。

还可以编译已解析的tree,然后将结果传递到evalexec来电。尽管如此,我发现它非常繁琐(你需要将ast.Expr的{​​{1}}属性包装在顶部分支的value中,所以我选择了更简单的方法(阅读和理解)只是传入字符串并让Python再次解析它的替代方法。

答案 1 :(得分:0)

你可以重构一下try-except。您的示例中没有真实的上下文,但假设您希望能够执行a=1然后评估a并获得1,那么您可以执行类似的操作。 ..

from code import InteractiveConsole
interpreter = InteractiveConsole()

def run(code):

    try: return eval(code.strip(), interpreter.locals)
    except: pass

    try: interpreter.runcode(code)
    except Exception as error: return error

这也适用于多行代码。

在不了解您的目标的情况下,很难说如何做到最好,但是您的原则很好,只需要整理。这个类似的answer再次包含了同一个try-except逻辑的最小版本,重点是更忠实地模仿解释器。

答案 2 :(得分:0)

你错过了一个,实际上有三个函数与执行代码有关,而你错过的函数是compile()

compile()需要三个必需的参数,要编译的代码,正在编译的模块的名称,它将出现在源自该代码的回溯中,以及"模式"。 mode参数应该是" exec"之一,用于编译整个模块," eval"用于编译简单表达式,以及"单个",它应该是一行交互式输入!

在所有三种情况下,您都将返回的code对象传递给eval,并带有所需的上下文:

>>> c = compile("if 1 < 2:\n    print(3)", "<string>", "single")
>>> eval(c)
3
>>>