I'm making a little toy command window with Tk, and currently trying to make it copy some interpreter behavior.
I'd never scrutinized the interpreter before, but it's decisions on when to print a value are a little mystifying.
>>> 3 + 4 # implied print(...)
7
>>> 3 # implied print(...)
3
>>> a = 3 # no output, no implied print(...), bc result is None maybe?
>>> None # no output, no print(...) implied... doesn't like None?
>>> print(None) # but it doesn't just ban all Nones, allows explicit print()
None
>>> str(None) # unsurprising, the string 'None' is just a string, and echoed
'None'
The goal is to mimic this behavior, printing some Nones, not others (made slightly more complicated because I'm not entirely sure what the rules are).
So, turning to my program, I have history_text and entry_text, which are StringVar()s that control a label above an entry box in the Tk window. Then the following event is bound to the Return key, to process commands and update the history with the result.
def to_history(event):
print("command entered") # note to debugging window
last_history = history_text.get()
# hijack stdout
buffer = io.StringIO('')
sys.stdout = buffer
# run command, output to buffer
exec(entry_text.get())
# buffered output to a simple string
buffer.seek(0)
buffer_str = ''
for line in buffer.readlines():
# maybe some rule goes here to decide if an implied 'print(...)' is needed
buffer_str = buffer_str + line + '\n'
# append typed command for echo
new_history = entry_text.get() + '\n' + buffer_str
# cleanup (let stdout go home)
sys.stdout = sys.__stdout__
buffer.close()
history_text.set(last_history + "\n" + new_history)
entry_text.set('')
As is, it does not provide any output for a simple entry of '3' or 'None' or even '3 + 4'. Adding an implied print() statement all the time seems to print too often, I don't skip the print for 'None' or 'a = 3' type statements.
I found some documentation for sys.displayhook, which seems to govern when the interpreter will actually display a result, but I'm not sure how to use it here. I thought I could just wrap sys.displayhook() around my exec() call, and have it do all this work for me... but found that it does not imply print() statements for statements like '3 + 4' or '3'.
Any suggestions? Am I on the right track with sys.displayhook?