How to use idlelib.PyShell to embed an interpreter in a tkinter program? How to use idlelib.PyShell to embed an interpreter in a tkinter program? tkinter tkinter

How to use idlelib.PyShell to embed an interpreter in a tkinter program?


Some details of what you must do may depend on what you want to do with IDLE's Shell once you have it running. I would like to know more about that. But let us start simple and make the minimum changes to pyshell.main needed to make it run with other code.

Note that in 3.6, which I use below, PyShell.py is renamed pyshell.py. Also note that everything here amounts to using IDLE's private internals and is 'use at your own risk'.

I presume you want to run Shell in the same process (and thread) as your tkinter code. Change the signature to

def main(tkroot=None):

Change root creation (find # setup root) to

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

In current 3.6, there are a couple more lines to be indented under if not tkroot:

    if use_subprocess and not testing:        NoDefaultRoot()

Guard mainloop and destroy (at the end) with

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

The above adds 'dependency injection' of a root window to the function. I might add it in 3.6 to make testing (an example of 'other code') easier.

The follow tkinter program now runs, displaying the both the root window and an IDLE shell.

from tkinter import *from idlelib import pyshellroot = 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()

You should be able to call pyshell.main whenever you want.