Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print output from a script in gui called in another Tkinter script?

I have tried using several different similar solutions that I have found online, but none seem to quite do what I am aiming for.

I want to call an external script (helloworld.py) into my tkinter gui. I want this called script (helloworld.py) to execute all the functions that are contained in it upon a button press in the gui and print the resulting outputs into the gui, not the console. I have found some solutions which will print the output to the console, but I am unable to get it to display in the gui. Any solutions that I have found that print to the gui do not work when I try to get the output to come from a called external script.

I appreciate any help. I am definitely a novice, so I apologize for what is probably a basic question and the inability to connect the dots for myself on similar questions asked on here. Below is one of the versions of code that I am currently working with. Thank you in advance for your help!

import Tkinter
import sys
import subprocess
sys.path.append('/users/cmbp')

def callback():
    import os
    print subprocess.call('python /users/cmbp/p4e/helloworld.py', 
shell=True)
    lbl = Tkinter.Label(master)
    lbl.pack()

master = Tkinter.Tk()
master.geometry('200x90')
master.title('Input Test')

Btn1 = Tkinter.Button(master, text="Input", command=callback)
Btn1.pack()

master.mainloop()

EDIT

I also started having some success with trying to import the called script as a module. The problem with this is I can only get one function to print out from the called script even though there are multiple functions that I want to try and call (I just want the entire called script to print out all the results of its functions).

Here is an example of a script that I want to call helloworld.py:

def cooz():
    return ('hello worldz!')

def tooz():
    return ("here is another line")

def main():
    return cooz()
    return tooz()

And here is an example of the tkinter gui script that is trying to import helloworld.py:

import Tkinter as tk
import helloworld

def printSomething():
    y = helloworld.main()
    label = tk.Label(root, text= str(y))
    label.pack()


root = tk.Tk()
root.geometry('500x200')
root.title('Input Test')

button = tk.Button(root, text="Print Me", command=printSomething)
button.pack()

root.mainloop()

This results in only the first function printing ('hello worldz!'). Any thoughts on why it only will return one line and not the entire helloworld.py script?

like image 985
Philalethes Avatar asked Jan 29 '26 17:01

Philalethes


1 Answers

You can use subprocess.check_output() to get output and assign to Label

You can also import script and execute function from script.

import test
test.function()

But first you will have to redirect sys.stdout using class with write() and then it will catch all printed text.

You can redirect sys.stdout to variable (see StdoutRedirector) and then you can edit it (ie. strip \n at the end) or you can redirect directly to Label (see StdoutRedirectorLabel)

import Tkinter as tk

# -----

import subprocess

def callback1():
    cmd = 'python test.py'

    # it will execute script which runs only `function1`
    output = subprocess.check_output(cmd, shell=True)

    lbl['text'] = output.strip()

# -----

class StdoutRedirector(object):

    def __init__(self):
        # clear before get all values
        self.result = ''

    def write(self, text):
        # have to use += because one `print()` executes `sys.stdout` many times
        self.result += text

def callback2():

    import test

    # keep original `sys.stdout
    old_stdout = sys.stdout

    # redirect to class which has `self.result`
    sys.stdout = StdoutRedirector()

    # it will execute only `function2`
    test.function2()

    # assign result to label (after removing ending "\n")
    lbl['text'] = sys.stdout.result.strip()

    # set back original `sys.stdout
    sys.stdout = old_stdout

# -----

import sys

class StdoutRedirectorLabel(object):

    def __init__(self, widget):
        self.widget = widget
        # clear at start because it will use +=
        self.widget['text'] = ''

    def write(self, text):
        # have to use += because one `print()` executes `sys.stdout` many times
        self.widget['text'] += text

def callback3():

    import test

    # keep original `sys.stdout
    old_stdout = sys.stdout

    # redirect to class which will add text to `lbl`
    sys.stdout = StdoutRedirectorLabel(lbl)

    # it will execute only `function3` and assign result to Label (with ending "\n")
    test.function3()

    # set back original `sys.stdout
    sys.stdout = old_stdout

# --- main ---

master = tk.Tk()
master.geometry('200x200')

lbl = tk.Label(master, text='')
lbl.pack()

btn1 = tk.Button(master, text="subprocess", command=callback1)
btn1.pack()

btn2 = tk.Button(master, text="StdoutRedirector", command=callback2)
btn2.pack()

btn3 = tk.Button(master, text="StdoutRedirectorLabel", command=callback3)
btn3.pack()

master.mainloop()

test.py

def function1():
    print('function 1')

def function2():
    print('function 2')

def function3():
    print('function 3')

if __name__ == '__main__':
    function1() 
like image 151
furas Avatar answered Jan 31 '26 06:01

furas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!