¿Cómo imprimir la salida de una secuencia de comandos en gui llamada en otra secuencia de comandos Tkinter?

He intentado usar varias soluciones similares diferentes que he encontrado en línea, pero ninguna parece hacer lo que estoy buscando.

Quiero llamar un script externo (helloworld.py) a mi tkinter gui. Quiero que este script llamado (helloworld.py) ejecute todas las funciones contenidas en él al presionar un botón en el gui e imprimir las salidas resultantes en el gui, no en la consola. He encontrado algunas soluciones que imprimirán la salida en la consola, pero no puedo mostrarla en la interfaz gráfica de usuario. Cualquier solución que he encontrado que imprime en la interfaz gráfica de usuario no funciona cuando bash que la salida provenga de un script externo llamado.

Aprecio cualquier ayuda. Definitivamente soy un novato, así que me disculpo por lo que probablemente sea una pregunta básica y la incapacidad de conectar los puntos por mí mismo en preguntas similares que se hacen aquí. A continuación se muestra una de las versiones de código con las que estoy trabajando actualmente. ¡Gracias de antemano por su ayuda!

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

EDITAR

También comencé a tener cierto éxito al intentar importar el script llamado como un módulo. El problema con esto es que solo puedo obtener una función para imprimir desde el script llamado aunque hay varias funciones que quiero probar y llamar (solo quiero que todo el script llamado imprima todos los resultados de sus funciones).

Aquí hay un ejemplo de un script que quiero llamar helloworld.py:

 def cooz(): return ('hello worldz!') def tooz(): return ("here is another line") def main(): return cooz() return tooz() 

Y aquí hay un ejemplo de la secuencia de comandos tkinter gui que intenta importar 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() 

Esto da como resultado que solo se imprima la primera función (‘hola worldz!’). ¿Alguna idea sobre por qué solo devolverá una línea y no todo el script de helloworld.py?

Puede usar subprocess.check_output() para obtener resultados y asignarlos a Label

También puede import script y ejecutar la función desde el script.

 import test test.function() 

Pero primero tendrá que redirigir sys.stdout usando class con write() y luego capturará todo el texto impreso.

Puede redirigir sys.stdout a la variable (ver StdoutRedirector ) y luego editarlo (es decir, desnudar \n al final) o puede redirigir directamente a Label (ver 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() 

En un método cuando se ejecuta una línea con return ... no se verá nada más que venga después de esa línea, ya que en su segunda línea de return ... es efectivamente inútil, ya que el return cooz() se ejecuta incondicionalmente . Usted podría simplemente reemplazar su main con:

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

y en consecuencia su printSomething :

 x, y = helloworld.main() 

Devolviendo todos los métodos / funciones desde un script sin pasar explícitamente nombres de métodos:

Bueno, estoy corregido , basado en esta respuesta puedes hacerlo de manera bastante simple. Para llamar a todos los métodos o funciones, esta respuesta ayudó mucho.

Digamos que hay un script llamado 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)) 

está en el mismo directorio que el script GUI a continuación:

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

que devuelve la salida de la consola de todos los métodos y funciones en hello_world.py como una cadena. Basándose en esta sugerencia , a continuación, coloca esa cadena en un campo de texto .