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

后端 未结 2 1902
隐瞒了意图╮
隐瞒了意图╮ 2021-02-11 01:49

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

2条回答
  •  野的像风
    2021-02-11 02:12

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

提交回复
热议问题