Seite 1 von 1

Konsolenausgabe in Fenster anzeigen

Verfasst: Dienstag 28. April 2009, 12:39
von Daniela
Hallo an alle,

ich hab nochmal ne Frage. Und zwar möchte ich in meiner GUI ein Feld haben, in welchem die Print-Anweisungen aus einem anderen Programm angezeigt werden. Das Text-Feld soll quasie wie die normale Konsole fungieren. Nur das, dass was normalerweise auf der Konsole angezeigt wird, jetzt in dem GUI-Fenster in dem Text-Widget reingeschrieben werden.

Ich hatte schon irgendwo gelesen, dass der Standard-Output umgelegt/umgeleitet werden muss, nur wie funktioniert das/funktioniert das überhaupt, wenn die print-Anweisungen aus einem anderen Programm/Python-Skript kommen.

Danke schonmal für eure Hilfe

Daniela

Re: Konsolenausgabe in Fenster anzeigen

Verfasst: Dienstag 28. April 2009, 14:23
von numerix
Daniela hat geschrieben:Hallo an alle,

ich hab nochmal ne Frage. Und zwar möchte ich in meiner GUI ein Feld haben, in welchem die Print-Anweisungen aus einem anderen Programm angezeigt werden. Das Text-Feld soll quasie wie die normale Konsole fungieren. Nur das, dass was normalerweise auf der Konsole angezeigt wird, jetzt in dem GUI-Fenster in dem Text-Widget reingeschrieben werden.

Ich hatte schon irgendwo gelesen, dass der Standard-Output umgelegt/umgeleitet werden muss, nur wie funktioniert das/funktioniert das überhaupt, wenn die print-Anweisungen aus einem anderen Programm/Python-Skript kommen.
Wenn das "andere Programm" ein Programm ist, das du zur Laufzeit deines Python-Programms quasi als Subprozess von diesem aus starten willst/kannst, dann geht das mit Hilfe des subprocess-Moduls. Die Konsolenausgabe dieses Programms kannst du dann abfangen und selbst weiter verarbeiten.

Wenn das "andere Programm" ein Programm ist, das schon vor Beginn deines Python-Programms läuft und auf die Konsole weiterhin Ausgaben produziert, dann sehe ich nicht, wie es gehen soll, falls du das "andere Programm" nicht dazu bewegen kannst, seinen Output an dein Python-Programm weiterzureichen.

Re: Konsolenausgabe in Fenster anzeigen

Verfasst: Dienstag 28. April 2009, 15:42
von Daniela
numerix hat geschrieben: Wenn das "andere Programm" ein Programm ist, das du zur Laufzeit deines Python-Programms quasi als Subprozess von diesem aus starten willst/kannst, dann geht das mit Hilfe des subprocess-Moduls. Die Konsolenausgabe dieses Programms kannst du dann abfangen und selbst weiter verarbeiten.
Es ist genau dieser Fall. Also es wird auf ein Button gedrückt und der ruft ein anderes Skript auf, in welchem verschiedene Statusmeldungen gesendet werden. Und diese sollen dann statt in der Konsole in das entsprechende Textfeld angezeigt werden.

Ich werd mir mal das modul von dem du gesprochen hast anschauen.
danke für den Hinweis.

Daniela

Verfasst: Dienstag 28. April 2009, 16:05
von yipyip
Hallo Daniela,
schau Dir mal an, was gerold zu diesem Thema
geschrieben hat:
http://www.python-forum.de/post-76403.html#76403

Da ich auch noch nie mit subprocess gearbeitet habe,
ist das folgende mit etwas Vorsicht zu geniessen
(bei mir funktionierts jedenfalls).

Datei p1.py (Rechte auf ausführbar):

Code: Alles auswählen

#!/usr/bin/env python

####

import time as ti
import sys

####

def count():

  for i in xrange(1, 22):
    #ti.sleep(0.1)
    #sys.stdout.flush()
    print '-'.join(['%s' % i] * i)
      
####
    
if __name__ == '__main__':

  count()
 
Datei p2.py (im gleichen Verzeichnis):

Code: Alles auswählen

#!/usr/bin/env python

####

import Tkinter as tk
import subprocess as sp
import os

####

class ShowWin(object):

  def __init__(self, root, *args):

    self.args = args
    self.root = root
    self.text = tk.Text(self.root)
    self.text.pack()
    self.button = tk.Button(self.root, text='Call Program',
                            command=lambda : self.show(*self.args))
    self.button.pack()

    
  def show(self, *args):

    proc = sp.Popen(args, stdout=sp.PIPE, cwd = os.curdir)
    for line in iter(proc.stdout.readline, ''):
      self.text.insert(tk.END, line)
      
    
####
    
if __name__ == '__main__':

  root = tk.Tk()
  win = ShowWin(root, 'p1.py')
  root.mainloop()
Dann einfach p2.py aufrufen.

:wink:
yipyip

Verfasst: Dienstag 28. April 2009, 16:27
von problembär
In "Python GePackt" ist folgendes merkwürdiges Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

import Tkinter as tk
import sys

class Ausgabefenster:

    def __init__(self):

        self.mw = tk.Tk()
        self.mw.title("Ausgabefenster")
        self.text = tk.Text(self.mw,
                            width = 80,
                            height = 10,
                            font = "Courier 14")
        self.text.pack()

    def write(self, s):
        self.text.insert(tk.END, s)

ausgabe = Ausgabefenster()
sys.stdout = ausgabe

print "Nanu ?"

ausgabe.mw.mainloop()
Gruß

Verfasst: Dienstag 28. April 2009, 17:10
von yipyip
War auch erst etwas verblüfft, bis ich dann gesehen hatte,
dass 'Ausgabefenster' ja eine 'write'-Methode hat.

'print' schreibt nach 'sys.stdout', einem File-Objekt, das
eine 'write'-Methode besitzt.
Mit

sys.stdout = ausgabe

wird dieses File-Objekt nun durch ein anderes Objekt ersetzt,
das ebenfalls eine 'write'-Methode besitzt.
Daher wird für die 'print'-Ausgabe nun die Methode von 'Ausgabefenster' benutzt.

:wink:
yipyip

Verfasst: Montag 4. Mai 2009, 07:31
von Daniela
Sorry dass ich mich so lange nicht gemeldet hab. Ich hatte kein Internet in der letzten Zeit.

Aber ich werde mir auf jedenfall mal die vorgeschlagenen Code-Schnippsel bzw. die Links anschauen.

Danke dafür schonmal.

Daniela

Verfasst: Montag 4. Mai 2009, 13:31
von Daniela
Ich hab jetzt die Lösung von problembär mal umgesetzt und es funktioniert eigentlich auch so, wie ich es haben will.
Nur werden die Meldungen die normalerweise auf der Konsole angezeigt werden, nicht in der gleichen Zeit in der GUI angezeigt.
Dass heißt, erst wenn das aufgerufene Programm beendet ist, werden alle Meldungen im GUI-Fenster angezeigt.
Normalerweise werden die Meldungen ja in "Echtzeit" sofort auf der Konsole ausgegeben, nur jetzt beim "umlenken" geschieht es erst wenn alles schon vorbei ist.
Meine Vermutung ist ja, dass jetzt noch mit Threads das gearbeitet werden muss, da das aufrufende Programm sehr rechenintensiv ist und man in der Zeit, wo das Programm läuft auf die GUI nicht mehr zugreifen kann.

Ach ja und dann wollte noch wissen, wenn jetzt das Textfeld als Ersatzkonsole funktioniert, wie kann man das machen, das wenn es beschrieben wird, dass dann immer das Ende bzw. die letzten Zeilen angezeigt werden. Jetzt ist es so, dass bei längeren Einträgen man den Anfang sieht, aber wennn der Text jetzt mehr ist, als in das Widget passt, muss man noch selber scrollen und dass ist nicht umbedingt der Sinn und Zweck dieser "Ersatzkonsole".

Daniela

Verfasst: Dienstag 5. Mai 2009, 16:39
von yipyip
Mit
text_widget.see(tk.END)
hast Du immer die letzte Zeile im Blick.

Habe noch etwas mit 'after()' und 'update()' herumexperimentiert,
da aber die Gui blockiert wird, solange auf die nächste Zeile aus
der Pipe gewartet wird (auch wenn es nur wenige Millisekunden
sind), halte ich es für sinnvoller, einen zusätzlichen Thread
zu verwenden.
Zum Glück hat man sowas ja in seiner Snippet-Sammlung.

Testausgabefile p1.py:
http://paste.pocoo.org/show/115866/

Anzeigeprogramm (im folgenden threaded.py genannt):
http://paste.pocoo.org/show/115867/

threaded.py ohne Argumente zeigt die Ausgabe von p1.py an.

threaded.py Programm [Argumente für Programm]

zeigt das an, was nach stdout geschrieben wird,
wenn 'Programm' aufgerufen wird.
Vielleicht läufts ja auf Anhieb mit Deinem Rechenprogramm.

:wink:
yipyip

Verfasst: Mittwoch 6. Mai 2009, 10:46
von Daniela
Cool Dankeschön. Ich schau mal, wie ich das verwenden kann mit dem zusätzlichen Thread

daniela