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

放肆的年华 提交于 2019-11-30 07:42:20

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

In a method when a line with return ... is run, nothing else will be seen that comes after that line, as in your 2nd line of return ... is effectively useless as return cooz() is run unconditionally. You could simply replace your main with:

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

and accordingly your printSomething:

x, y = helloworld.main()

Returning all methods/functions from a script without explicitly passing method names:

Well, I stand corrected, based on this answer you can do it fairly simply. For calling all methods or functions this answer helped a lot.

Let's say there's a script named hello_world.py:

def hello_world():
    print("Hello World!")
    print("this is the 2nd line of this method")

def multiplication(*args):
    mult = 1
    for arg in args:
        mult *= arg

    return mult

def some_other_method():
    print("some other method")
    print(multiplication(2, 3, 5, 7))

is in the same directory as GUI script below:

import tkinter as tk    # required for the GUI
import subprocess       # required for redirecting stdout to GUI
import sys, inspect     # required for all methods and functions redirection
import hello_world      # the script file that is redirected

def redirect(module, method):
    '''Redirects stdout from the method or function in module as a string.'''
    proc = subprocess.Popen(["python", "-c",
        "import " + module.__name__ + ";" + module.__name__ + "." + method + "()"],
                                                                stdout=subprocess.PIPE)
    out = proc.communicate()[0]
    return out.decode('unicode_escape')

def redirect_module(module):
    '''Retruns all stdout from all methods or functions in module as a string.'''
    # to filter out non-method, and non-function attributes
    all_mtds_or_funcs = inspect.getmembers(sys.modules[module.__name__], 
                                                inspect.isfunction or inspect.ismethod)
    red_str_buffer = ""
    for method in all_mtds_or_funcs:
        red_str_buffer += redirect(module, method[0]) + "\n---\n"

    return red_str_buffer

def put_in_txt(module):
    '''Puts the redirected string in a text.'''
    txt.insert('1.0', redirect_module(module))

root = tk.Tk()
txt = tk.Text(root)
btn = tk.Button(root, text="Redirect")
btn['command'] = lambda module=hello_world : put_in_txt(module)

txt.pack()
btn.pack()

root.mainloop()

which returns console output of all methods and functions in hello_world.py as a string. Based on this suggestion it then puts that string in a Text field.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!