Python – How do I print the output of a gui script called in another Tkinter script?

How do I print the output of a gui script called in another Tkinter script?… here is a solution to the problem.

How do I print the output of a gui script called in another Tkinter script?

I’ve tried several different similar solutions I’ve found online, but none of them seem to quite hit my goal.

I want to call an external script (helloworld.py) into my tkinter gui. I want this button, called a script (helloworld.py), to perform all the functions it contains when pressed in the GUI and print the resulting output to the GUI, not the console. I found some solutions to print the output to the console, but I can’t show it in the GUI. When I try to get the output from the called external script, I find that any solution that prints to the GUI doesn’t work.

I appreciate any help. I’m definitely a newbie, so I apologize for this being probably a basic issue and for not being able to relate to myself on similar issues raised here. Here is one of the versions of the code I’m currently using. 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 trying to import the invoked script as a module with some success. The problem is that I can only print out one function from the called script, even though I want to try to call multiple functions (I just want the entire called script to print out all the results of its function).

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

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

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

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

Here is an example of a tkinter GUI script that tries 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 will only print the first function (“hello worldz!”). Any ideas on why it only returns one line instead of the entire helloworld.py script?

Solution

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

You can also import scripts and perform functions from scripts.

import test
test.function()

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

You can redirect sys.stdout to a variable (see StdoutRedirector), which you can then edit (i.e. in 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() 

Related Problems and Solutions