0

我有一些代码,例如:

    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"因为我想支持任何命令,而不仅仅是单个表达式。

并且使用 mode "exec",我也不会得到返回值。

那么,解决方案是什么?


上游建议:单次执行的编译标志以返回值而不是打印它


用例:Python 远程外壳​​。我已经为我的应用程序实现了这个,以便能够随时附加它。服务器socketcontrol模块客户端交互外壳实现

4

1 回答 1

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
于 2013-02-25T04:16:40.193 回答