0

everyone! I've run into a problem. Let's say I have a script that is launched using subprocess module from tkinter giu like this (params includes the name of the script):

p = Popen(['python.exe'] + params)

During being executed, my script has some messages that I want to be printed in my gui. While I was using console, I just did it with print function like this:

print(f'Connected to {ppm_file}')

What I now need to do, is to make this message be printed in a text widget in tkinter gui.

I suppose it implys using stdout, but I'm a newbie to this concept and find it a little bit hard to understand.

Thanks for your help!

agas0077
  • 7
  • 7

2 Answers2

0

In the text widget, you can insert by using following method:

txtbox.delete('1.0', END) # to remove any preceding text(ignore if empty)
txtbox.insert(END, 'Connected to {ppm_file}')  # insert the text you want
txtbox.insert(END, '\n') # additional insertion for example a newline character
Dude901
  • 153
  • 1
  • 9
  • But how do I get these strings from another process? – agas0077 Feb 05 '21 at 17:34
  • You can get the concerned value back to main script and then insert, for more details, please refer here: https://stackoverflow.com/questions/30664263/return-value-from-one-python-script-to-another – Dude901 Feb 05 '21 at 17:38
  • the link you gave almost covers my needs, but I have these prints all along my script, as they indicates the process status. As far as I understant, the question there covers the situation, when the print function is final. – agas0077 Feb 05 '21 at 17:48
  • Well, you can accumulate all the process statuses inside a `dict` or `list`, and then after returning it, iterate over it and insert it into the output textbox. – Dude901 Feb 05 '21 at 17:55
  • i might have explained it not clearly enough. I need these prints to be shown in my gui window once they are called, i.e. (script file starts with subprocess -> some actions carried out by the script -> script calls print function -> the message goes to gui instead of console -> some feurther actions -> script calls one more print -> the new message goes to gui instead of console -> etc) – agas0077 Feb 05 '21 at 18:07
  • I understood the issue in the first place, what I meant to say is you possibly cannot control one Tkinter UI from two separate scripts, I also faced this issue a week back in one of my projects and there were solutions stating to **import the main python file in the secondary script** and then insert from there, but I couldn't make it work. That's why I shifted my program to classes instead of scripts. – Dude901 Feb 05 '21 at 18:22
  • that's why I suggested to append all the statuses into a list or something similar and then insert that list in the txtbox, i.e. output all the statuses at once. Or you can also considering using OOPs and inherit the values, this way you can easily do the job you're looking to do. – Dude901 Feb 05 '21 at 18:30
  • 1
    yeah, now I've got you. I suppose OOP's the best way for now, though it requires a lot of rewritng))) thanks a lot anyway! – agas0077 Feb 05 '21 at 18:35
  • if somebody comes up with somthing simplier, please share) – agas0077 Feb 05 '21 at 18:35
  • Yes indeed, it does require a lot of rewriting. I've been in your shoes and know how it feels to rewrite hundreds of lines of code LOL. Also, you might consider accepting the answer as a solution and upvoting it if your needs are fulfilled for now. – Dude901 Feb 06 '21 at 04:05
0

You can capture the console output of the external script and insert the captured output into a Text widget.

Below is an example:

import tkinter as tk
import subprocess
import threading

root = tk.Tk()

logbox = tk.Text(root, width=80, height=20)
logbox.pack()

def capture_output():
    # "python -u" make stdout stream to be unbuffered
    p = subprocess.Popen(["python", "-u", "other.py"], stdout=subprocess.PIPE)
    while p.poll() is None: # process is still running
        logbox.insert("end", p.stdout.readline())
        logbox.see("end")
    logbox.insert("end", "--- done ---\n")

# use thread so that it won't block the application
tk.Button(root, text="Run", command=lambda: threading.Thread(target=capture_output, daemon=True).start()).pack()

root.mainloop()
acw1668
  • 40,144
  • 5
  • 22
  • 34