Tkinter, Subprocess: Only input() function not working when my python file is called using subprocess.Popen() "The output is displayed in tkinter"

Viewed 37

I am trying to create a python text editor. What I want to create in my app, is a textbox where the user writes python code, another box where the user will see the terminal output and a button to run the code. After a few days of research, I found out that terminal output can be shown by using the subprocess module. I used it, worked pretty well! I type print("hello world"), it works.

However, only one thing that did not work is when we run something like input("Enter your name: "). The program just crashes when I run it. This is where I got stuck for a long time. I know doing something like that is not easy because the output box is just a text widget. But, I have seen that many apps can do that so the input function might be possible.

The code below is a sample from my project:

from tkinter import *
import subprocess, os

def run():
    code = open(f"{os.getcwd()}/test2.py", 'w')
    code.write(input_box.get(1.0, END))
    code.close()

    process = subprocess.Popen("python3 test2.py", stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
    output, error = process.communicate()
    output_box.delete(1.0, END)
    output_box.insert(END, output)
    output_box.insert(END, error)

root = Tk()

input_box = Text(root)
input_box.grid(row=0, column=0)

output_box = Text(root)
output_box.grid(row=0, column=1)

btn = Button(root, text="Run", command=run)
btn.grid(row=1, column=0)

output_box.insert(1.0, "Output:\n")
output_box.bind('<BackSpace>', lambda _: 'break')

root.mainloop()

The program crashes here:The frozen screen when I click run button:

My current approach is to make my own input function hidden in the users code (this line of code does it): code.write(open(f"{os.getcwd()}/input_string.py", 'r').read(), input_box.get(1.0, END))

Here is input_string.py where it uses tkinter.simpledialog.askstring:

from tkinter import simpledialog

def input(prompt):
    ipt = simpledialog.askstring('input', prompt)
    return ipt

This works but I am open to better solutions here. I hope you understand my question and the effort I put into this.

0 Answers
Related