Вывод в стиле интерпретатора в Python 3 (может быть, о sys.displayhook?)

Я делаю небольшое игрушечное командное окно с Tk, и в настоящее время пытаюсь заставить его скопировать некоторое поведение интерпретатора.

Я никогда раньше не изучал интерпретатор, но его решение о том, когда печатать значение, немного загадочно.

>>> 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'

Цель состоит в том, чтобы подражать этому поведению, печатая одни Nones, а не другие (сделаны немного более сложными, потому что я не совсем уверен, каковы правила).

Итак, обращаясь к моей программе, у меня есть history_text и entry_text, которые являются StringVar(), которые контролируют метку над полем ввода в окне Tk. Затем следующее событие связывается с клавишей Return, чтобы обработать команды и обновить историю с результатом.

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('')

Таким образом, он не предоставляет никакого вывода для простой записи "3" или "None" или даже "3 + 4". Кажется, что добавление неявного оператора print() все время печатает слишком часто, я не пропускаю печать для операторов типа "None" или "a = 3".

Я нашел некоторую документацию для sys.displayhook, которая, кажется, определяет, когда интерпретатор действительно отобразит результат, но я не уверен, как его использовать здесь. Я подумал, что могу просто обернуть sys.displayhook() вокруг моего вызова exec() и заставить его выполнять всю эту работу за меня... но обнаружил, что это не подразумевает операторов print() для операторов типа '3 + 4' или '3'.

Какие-либо предложения? Я на правильном пути с sys.displayhook?

1 ответ

Решение

Переводчик распечатывает repr(result) только если result is not None,

Там нет "подразумевается prints", как вы думали.

  • 3 + 4 результаты к 7, так repr(7) печатается
  • a = 3 это задание, я думаю, что ничего не печатается, потому что он не работает с eval
  • None результаты к Noneтак что ничего не печатается
  • print(None) результаты к None (поскольку print функция ничего не возвращает), поэтому ничего не печатается. Тем не менее print сама функция напечатала None,

Я, честно говоря, не читал ваш код, но вот функция, которая принимает строку с кодом и выдает тот же результат, что и интерпретатор:

def interactive(code):
    try:
        result = eval(code)
        if result is not None:
            print(repr(result))
    except SyntaxError:
        exec(code)
Другие вопросы по тегам