New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
compile-flag for single-execution to return value instead of printing it #61496
Comments
Instead of printing the value, it might make more sense to return it and to leave it to the developer - there are many cases where it shouldn't end up on stdout but somewhere else. There could be an additional compile-flag which would make a code-object returning the value instead of printing it. Note that I have come up with a workaround: 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 My related StackOverflow question: |
If you know you have an expression and would like the value, you should use the "eval" mode. In the case of "single", you can adapt sys.displayhook to change where to print (if at all) the values. Note that "single" sometimes prints multiple values (try e.g. "for i in range(10):\n i\n"). |
I don't know that I have an expression and I want it also to work if it is not an expression. Basically I really want the 'single' behavior. (My not-so-uncommon use case: Have an interactive shell where the output on stdout does not make sense. Also I might want to save references to returned values.) displayhook is not an option in any serious bigger project because you don't want to do overwrite that globally. |
Albert: enhancements can only go in future releases. Also, when a core developer rejects a suggestion and closes an issue, it is better to just request a re-open, or otherwise post to python-list or python-ideas to refine the idea and possible gather more support. We really do not like Status header setting wars. Mode 'single' is not what you actually want. Its only purpose is add the print that you do not want*. It is otherwise the same as mode 'exec' (except for requiring exactly 1 statement rather than 0 to n). What you are asking is that 'single' act like 'eval' for expressions. That is what your interactive_py_compile effectively does. However, this can be done much easier and without being CPython 2 specific as follows: def ee_compile(code, src=''):
try:
return compile(code, src, 'eval')
except SyntaxError:
return compile(code, src, 'exec') # or 'single' would work
a = eval(ee_compile('1+1'))
b = eval(ee_compile('c = 3'))
print(a, b, c)
# 2 None 3 With 2.7, your function gives the exact same result. I could not get it to run on 3.3: even after removing the ord calls and changing chr to bytes (and making the arg a tuple), the CodeType call failed.
for statement in user_input():
if statement:
exec(compile(statement, '<input>', 'single')) You can replace the last line with Anyway, I agree with Georg that we do not need to modify compile. I have opened a separate issue bpo-19290 about clarifying compile modes and their interaction with eval. |
Thanks a lot for the long and detailed response! I didn't meant to start a header war; I thought that my request was misunderstood and thus the header changes were by mistake. But I guess it is a good suggestion to leave that decision to a core dev. I still thing that this would have been more straight-forward in the first place: for statement in user_input():
if statement:
value = exec(compile(statement, '<input>', 'single'))
if value is not None: print value Because it is more explicit. But because introducing such an incompatible change is bad, I thought it's a good idea to add another compile-mode. Your |
Terry, thanks for your explanation; I was trying to find some time to write something similar... |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: