Domanda

Ho creato un programma che consente di stampare i risultati sulla linea di comando. (È server e la stampa di registro sulla riga di comando.)

Ora, voglio vedere lo stesso risultato di GUI.

Come faccio a reindirizzare i risultati della riga di comando di GUI?

Per cortesia, indicate un trucco per trasformare facilmente un'applicazione console di semplice interfaccia grafica.

Si noti che dovrebbe funzionare su Linux e Windows.

È stato utile?

Soluzione

Si potrebbe creare un wrapper script che esegue il programma da riga di comando come un processo sub, quindi aggiungere l'output a qualcosa di simile a un widget di testo.

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

dove lo script è il tuo programma. È ovviamente possibile stampare gli errori in un colore diverso, o qualcosa del genere.

Altri suggerimenti

Per visualizzare il sottoprocesso uscita in una GUI mentre è ancora in esecuzione , una soluzione stdlib solo portatile che funziona sia su Python 2 e 3 deve usare un thread in background:

#!/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()

L'essenza della soluzione è:

  • mettere l'uscita sottoprocesso nella coda in un thread in background
  • ottenere l'uscita dalla coda nel thread GUI.
.

cioè, chiamare process.readline() in thread in background -> coda -> etichetta aggiornamento GUI nel thread principale. Related kill-process.py (senza polling - una soluzione portatile meno che event_generate utilizza in un thread in background).

Ridirezionamento stdout a un metodo write () che aggiorna la vostra interfaccia grafica è un modo per andare, e probabilmente il più veloce - anche se l'esecuzione di un sottoprocesso è probabilmente una soluzione più elegante.

reindirizzare stderr Solo una volta che sei davvero sicuro che è installato e funzionante, però!

Esempio implimentation (file GUI e script di test):

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!"

Ci dispiace per il mio cattivo inglese. Io in realtà, usato un modo diverso per stampare Command Prompt uscita nel mio nuovo strumento di automazione. Si prega di trovare quei passaggi di seguito.

1> Crea un file bat e reindirizzare l'output ad un file di log. Comando del prompt dei comandi: tasklist /svc

2> Fare leggere quel file con Python 3.x. `ProcessedFile = open ( 'D: \ LOG \ taskLog.txt', 'r')

3> Il passo Finale. ttk.Label(Tab4, text=[ProcessFile.read()]).place(x=0, y=27)

** Quindi Si informa che, non ho includere barra di scorrimento in questo codice ancora.

Schermata della pubblicazione:

entrare descrizione dell'immagine qui

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top