Python:在交互式终端中使用eval。如何获得回报价值。什么编译模式

时间:2013-02-25 02:54:17

标签: python compilation eval

我有一些代码:

    try:
        c = compile(s, COMPILE_STRING_FN, "single")
    except Exception as e:
        answer = (idx, "compile-exception", (e.__class__.__name__, str(e)))
    else:
        try:
            ret = eval(c, globals, locals)
        except Exception as e:
            answer = (idx, "eval-exception", (e.__class__.__name__, str(e)))
        else:
            if ret is not None:
                try:
                    ret = str(ret)
                except Exception as e:
                    ret = "<str-cast exception: %s: %s>" % (e.__class__.__name__, str(e))
            answer = (idx, "return", ret)

这不会按预期工作,因为ret始终是None - 如果有值,则会打印相反的值。这不是我想要的 - 我希望在ret中获得它。

似乎"single"对我来说不是正确的编译模式。此外,s = "def f(): return 42"不起作用。

然而,"eval"都不是,因为我想支持任何命令,而不仅仅是单个表达式。

使用模式"exec",我也不会得到返回值。

那么,解决方案是什么?


上游建议:compile-flag for single-execution to return value instead of printing it


用例:Python远程shell。我为my application实现了这个功能,以便能够随时随地附加它。 server socketcontrol moduleclient interactive shell implementation

1 个答案:

答案 0 :(得分:0)

我可以使用此功能代替compile(s, COMPILE_STRING_FN, "single")

def interactive_py_compile(source, filename="<interactive>"):
    c = compile(source, filename, "single")

    # we expect this at the end:
    #   PRINT_EXPR     
    #   LOAD_CONST
    #   RETURN_VALUE    
    import dis
    if ord(c.co_code[-5]) != dis.opmap["PRINT_EXPR"]:
        return c
    assert ord(c.co_code[-4]) == dis.opmap["LOAD_CONST"]
    assert ord(c.co_code[-1]) == dis.opmap["RETURN_VALUE"]

    code = c.co_code[:-5]
    code += chr(dis.opmap["RETURN_VALUE"])

    CodeArgs = [
        "argcount", "nlocals", "stacksize", "flags", "code",
        "consts", "names", "varnames", "filename", "name",
        "firstlineno", "lnotab", "freevars", "cellvars"]
    c_dict = dict([(arg, getattr(c, "co_" + arg)) for arg in CodeArgs])
    c_dict["code"] = code

    import types
    c = types.CodeType(*[c_dict[arg] for arg in CodeArgs])
    return c