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

1

2

I need to embed an interative python interpreter into my tkinter program. Could anyone help me out as to how to integrate it?

I have already looked at the main() function, but it's way to complex for my needs, but I can't seem to reduce it without breaking it.

List answered 16/8, 2016 at 14:25 Comment(3)
Others have asked about adding a console to tkinter program, but I don't remember anyone specifically suggesting and asking about using IDLE's Shell.Fulgurous
@TerryJanReedy I would prefer a console, but I have yet to receive an answer from my previous question regarding that. If you could look at the question here my circumstances are further explained. Thanks for the answer though, it will make a good temporary solution.List
I hope you find it useful. I am pretty sure I will, though I only realized this after writing it ;-).Fulgurous
F
3

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

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

Fulgurous answered 16/8, 2016 at 20:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.