Как использовать idlelib.PyShell для встраивания интерпретатора в программу tkinter?

Мне нужно встроить интерактивный интерпретатор Python в мою программу tkinter. Может ли кто-нибудь помочь мне в том, как его интегрировать?

Я уже рассматривал функцию main(), но она слишком сложна для моих нужд, но я не могу уменьшить ее, не нарушив ее.


person Hayden Ravenscroft    schedule 16.08.2016    source источник
comment
Другие спрашивали о добавлении консоли в программу tkinter, но я не помню, чтобы кто-то специально предлагал и спрашивал об использовании IDLE Shell.   -  person Terry Jan Reedy    schedule 16.08.2016
comment
@TerryJanReedy Я бы предпочел консоль, но я еще не получил ответа на свой предыдущий вопрос по этому поводу. Если вы могли бы посмотреть на вопрос здесь, мои обстоятельства будут объяснены более подробно. Спасибо за ответ, это будет хорошим временным решением.   -  person Hayden Ravenscroft    schedule 17.08.2016
comment
Надеюсь, вы сочтете это полезным. Я почти уверен, что сделаю это, хотя я понял это только после того, как написал его ;-).   -  person Terry Jan Reedy    schedule 17.08.2016


Ответы (1)


Некоторые детали того, что вы должны делать, могут зависеть от того, что вы хотите делать с оболочкой IDLE после ее запуска. Я хотел бы узнать об этом больше. Но давайте начнем с простого и внесем в pyshell.main минимальные изменения, необходимые для его работы с другим кодом.

Обратите внимание, что в версии 3.6, которую я использую ниже, PyShell.py переименован в pyshell.py. Также обратите внимание, что все здесь сводится к использованию частных внутренних компонентов IDLE и «используйте на свой страх и риск».

Я предполагаю, что вы хотите запустить Shell в том же процессе (и потоке), что и ваш код tkinter. Измените подпись на

def main(tkroot=None):

Измените создание корня (найдите # setup root) на

if not tkroot:
    root = Tk(className="Idle")
    root.withdraw()
else:
    root = tkroot

В текущей версии 3.6 есть еще пара строк с отступом под if not tkroot:

    if use_subprocess and not testing:
        NoDefaultRoot()

Защитите главный цикл и уничтожьте (в конце) с помощью

if not tkroot:
    while flist.inversedict:  # keep IDLE running while files are open.
        root.mainloop()
    root.destroy()
# else leave mainloop and destroy to caller of main

Вышеупомянутое добавляет к функции «инъекцию зависимостей» корневого окна. Я мог бы добавить его в 3.6, чтобы упростить тестирование (пример «другого кода»).

Теперь запускается следующая программа tkinter, отображающая как корневое окно, так и оболочку IDLE.

from tkinter import *
from idlelib import pyshell

root = Tk()
Label(root, text='Root id is '+str(id(root))).pack()
root.update()
def later():
    pyshell.main(tkroot=root)
    Label(root, text='Use_subprocess = '+str(pyshell.use_subprocess)).pack()

root.after(0, later)
root.mainloop()

Вы должны иметь возможность вызывать pyshell.main, когда захотите.

person Terry Jan Reedy    schedule 16.08.2016