Redirect-Befehlszeile führt zu einer tkinter-GUI

Ich habe ein Programm erstellt, das die Ergebnisse auf der Befehlszeile druckt. (Es ist Server und es druckt Log-Befehlszeile.)

Nun möchte ich das gleiche Ergebnis zu GUI sehen.

Wie kann ich Befehlszeilenergebnisse an GUI weiterleiten?

Bitte schlagen Sie einen Trick vor, um die Konsolenanwendung einfach auf einfache GUI zu verwandeln.

Beachten Sie, dass es auf Linux und Windows funktionieren sollte.

  • Kochbuch-GUI-Schnittstelle für ein Kommandozeilen-Skript
  • Tkinter matplotlib-Diagramm kann nicht mit Schaltflächen und benutzerdefinierten Daten aktualisiert werden
  • Der beste Weg, um den Namen einer Schaltfläche zu erhalten, die ein Ereignis angerufen hat?
  • Kann nicht zerstören wx.Dialog in wxpython
  • Warum wird mein Dialogfeld nicht angezeigt, wenn fullscr = True?
  • Cross Platform, Sprache Agnostic GUI Markup Sprache?
  • Machen Sie Ihr Programm USE eine Gui
  • Hinzufügen eines Widgets mit einem Button - wxPython
  • 3 Solutions collect form web for “Redirect-Befehlszeile führt zu einer tkinter-GUI”

    Sie könnten einen Skript-Wrapper erstellen, der Ihr Kommandozeilenprogramm als Subprozess ausführt, dann fügen Sie die Ausgabe zu etwas wie einem Text-Widget hinzu.

    from tkinter import * import subprocess as sub p = sub.Popen('./script',stdout=sub.PIPE,stderr=sub.PIPE) output, errors = p.communicate() root = Tk() text = Text(root) text.pack() text.insert(END, output) root.mainloop() 

    Wo Skript dein Programm ist. Sie können offensichtlich die Fehler in einer anderen Farbe drucken, oder so ähnlich.

    Um die Unterprozeßausgabe in einer GUI anzuzeigen, während sie noch läuft , muss eine tragbare stdlib-only-Lösung, die auf Python 2 und 3 arbeitet, einen Hintergrund-Thread verwenden:

     #!/usr/bin/python """ - read output from a subprocess in a background thread - show the output in the GUI """ import sys from itertools import islice from subprocess import Popen, PIPE from textwrap import dedent from threading import Thread try: import Tkinter as tk from Queue import Queue, Empty except ImportError: import tkinter as tk # Python 3 from queue import Queue, Empty # Python 3 def iter_except(function, exception): """Works like builtin 2-argument `iter()`, but stops on `exception`.""" try: while True: yield function() except exception: return class DisplaySubprocessOutputDemo: def __init__(self, root): self.root = root # start dummy subprocess to generate some output self.process = Popen([sys.executable, "-u", "-c", dedent(""" import itertools, time for i in itertools.count(): print("%d.%d" % divmod(i, 10)) time.sleep(0.1) """)], stdout=PIPE) # launch thread to read the subprocess output # (put the subprocess output into the queue in a background thread, # get output from the queue in the GUI thread. # Output chain: process.readline -> queue -> label) q = Queue(maxsize=1024) # limit output buffering (may stall subprocess) t = Thread(target=self.reader_thread, args=[q]) t.daemon = True # close pipe if GUI process exits t.start() # show subprocess' stdout in GUI self.label = tk.Label(root, text=" ", font=(None, 200)) self.label.pack(ipadx=4, padx=4, ipady=4, pady=4, fill='both') self.update(q) # start update loop def reader_thread(self, q): """Read subprocess output and put it into the queue.""" try: with self.process.stdout as pipe: for line in iter(pipe.readline, b''): q.put(line) finally: q.put(None) def update(self, q): """Update GUI with items from the queue.""" for line in iter_except(q.get_nowait, Empty): # display all content if line is None: self.quit() return else: self.label['text'] = line # update GUI break # display no more than one line per 40 milliseconds self.root.after(40, self.update, q) # schedule next update def quit(self): self.process.kill() # exit subprocess if GUI is closed (zombie!) self.root.destroy() root = tk.Tk() app = DisplaySubprocessOutputDemo(root) root.protocol("WM_DELETE_WINDOW", app.quit) # center window root.eval('tk::PlaceWindow %s center' % root.winfo_pathname(root.winfo_id())) root.mainloop() 

    Das Wesen der Lösung ist:

    • Setzen Sie die Subprocess-Ausgabe in die Warteschlange in einem Hintergrund-Thread
    • Bekomme die Ausgabe aus der Warteschlange im GUI-Thread.

    process.readline() call process.readline() im Hintergrund-Thread -> Warteschlange -> GUI-Label im Haupt-Thread aktualisieren.

    Umleiten von Stdout zu einer write () -Methode, die Ihre Gui aktualisiert, ist ein Weg zu gehen, und wahrscheinlich das schnellste – obwohl das Ausführen eines Unterprozesses ist wahrscheinlich eine elegantere Lösung.

    Nur umstürzen stderr, sobald du wirklich zuversichtlich bist, dass es los ist und funktioniert aber!

    Beispielimplimentation (Gui-Datei und Testskript):

    Test_gui.py:

     from Tkinter import * import sys sys.path.append("/path/to/script/file/directory/") class App(Frame): def run_script(self): sys.stdout = self ## sys.stderr = self try: del(sys.modules["test_script"]) except: ## Yeah, it's a real ugly solution... pass import test_script test_script.HelloWorld() sys.stdout = sys.__stdout__ ## sys.stderr = __stderr__ def build_widgets(self): self.text1 = Text(self) self.text1.pack(side=TOP) self.button = Button(self) self.button["text"] = "Trigger script" self.button["command"] = self.run_script self.button.pack(side=TOP) def write(self, txt): self.text1.insert(INSERT, txt) def __init__(self, master=None): Frame.__init__(self, master) self.pack() self.build_widgets() root = Tk() app = App(master = root) app.mainloop() 

    Test_script.py:

     print "Hello world!" def HelloWorld(): print "HelloWorldFromDef!" 
    Python ist die beste Programmiersprache der Welt.