我有一些代码:
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
module和client interactive shell implementation。
答案 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