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
Konsolenausgabe in Fenster anzeigen
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.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 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.
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.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.
Ich werd mir mal das modul von dem du gesprochen hast anschauen.
danke für den Hinweis.
Daniela
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):
Datei p2.py (im gleichen Verzeichnis):
Dann einfach p2.py aufrufen.
yipyip
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()
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()

yipyip
Zuletzt geändert von yipyip am Dienstag 28. April 2009, 22:20, insgesamt 1-mal geändert.
In "Python GePackt" ist folgendes merkwürdiges Beispiel:
Gruß
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()
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.
yipyip
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.

yipyip
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
Aber ich werde mir auf jedenfall mal die vorgeschlagenen Code-Schnippsel bzw. die Links anschauen.
Danke dafür schonmal.
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
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
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.

yipyip
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.

yipyip