Seite 1 von 1

stdout "umlenken" Python3

Verfasst: Sonntag 11. November 2012, 15:36
von xvzf
Hallo,
gibt es eine Möglichkeit die Standartterminal Ausgabe in ein Textwidget
(PyQt4)umzuleiten?
Das ganze in Python3 ;)

Danke :)

Re: stdout "umlenken" Python3

Verfasst: Sonntag 11. November 2012, 15:55
von BlackJack
@xvzf: Jain. Du kannst `sys.stdout` durch ein eigenes Objekt ersetzen, dass die Ausgaben in ein Textfeld steckt. Aber dadurch wird ein Qt-Textfeld natürlich nicht zu einem vollwertigen Terminal(emulator).

Re: stdout "umlenken" Python3

Verfasst: Sonntag 11. November 2012, 16:01
von xvzf
Nein, das wollte ich auch nicht, dann hätte ich auch stdin müssen umlenken ;)

Kennst du einen Beispielcode ?

Re: stdout "umlenken" Python3

Verfasst: Montag 19. November 2012, 12:21
von snafu
Na, Beispielcode wäre dann wohl `sys.stdout = dein_objekt`, wobei dein Objekt sinnvollerweise eine passende `.write()`-Methode implementieren sollte, wie sie von Code, der in `stdout` schreiben will, erwartet wird. Oder geht es dir in Wirklichkeit vielleicht eher um die Umleitung (Pipe) von Programmausgaben?

Re: stdout "umlenken" Python3

Verfasst: Donnerstag 22. November 2012, 20:37
von xvzf
Dann erhalte ich folgende Fehlermeldung:

Code: Alles auswählen

    self.ui.textEdit.setText(sys.stdout)
TypeError: QTextEdit.setText(str): argument 1 has unexpected type '_io.TextIOWrapper'


Re: stdout "umlenken" Python3

Verfasst: Donnerstag 22. November 2012, 21:10
von lunar
@xvzf Das war sicher nicht das, wozu snafu geraten hat. Was bewirkt diese Zeile Deiner Meinung nach? Erwartest Du, dass die Standardausgabe irgendwie automagisch im Textfeld landet?!

Die Fehlermeldung ist ziemlich deutlich… so deutlich, dass Du – wenn Du sie nicht zu interpretieren weißt – besser erst einmal die Finger von GUI-Programmen lässt, weil Dir dann relativ sicher ein paar nötige Grundlagen fehlen. Sie sagt Dir, dass Du ein Dateiobjekt übergibst, wo einfacher Text in Form einer Zeichenkette erwartet wird.

Einem Textfeld kann man nur Text zuweisen. Die Standardausgabe unter sys.stdout ist aber nicht einfach Text, sondern ein Dateiobjekt, in das Text geschrieben wird. Deine Aufgabe ist, sys.stdout ein Dateiobjekt zuzuweisen, dass diese Ausgabe an das Textfeld weiterleitet. Das geschieht nicht automatisch. Dieses Objekt musst Du selbst implementieren, und die Implementierung ist eigentlich relativ trivial.

Re: stdout "umlenken" Python3

Verfasst: Sonntag 25. November 2012, 01:39
von AngelusNoctis

Re: stdout "umlenken" Python3

Verfasst: Sonntag 25. November 2012, 12:03
von snafu
Hier mal eine mögliche Implementierung:

Code: Alles auswählen

from StringIO import StringIO
import sys

from PyQt4.QtCore import pyqtSignal, QObject
from PyQt4.QtGui import QApplication, QTextEdit


class TextStream(StringIO, QObject):
    inputReceived = pyqtSignal(str)

    def __init__(self, buf=''):
        StringIO.__init__(self, buf)
        QObject.__init__(self)

    def write(self, s):
        StringIO.write(self, s)
        self.inputReceived.emit(s)
        

def main(args=[]):
    app = QApplication(args)
    sys.stdout = TextStream()
    textEdit = QTextEdit()
    sys.stdout.inputReceived.connect(textEdit.setText)
    textEdit.show()
    sys.stdout.write('Spam')
    app.exec_()


if __name__ == '__main__':
    main(sys.argv)
Ein paar Anmerkungen: Es existiert zwar `QTextStream`, aber ich finde es als Ersatz für `sys.stdout` eher ungeeignet. Daher der Rückgriff auf das hier schon erwähnte `StringIO`. Wie man sieht, habe ich mich entschieden, eine Art abstrakte Zwischenschicht zu schreiben, die ganz in Qt-Manier erstmal nur signalisert, dass neuer Input da ist, ohne dass schon eine spezielle Callback-Funktion oder ein spezifisches Empfänger-Widget angegeben werden müsste. Das mit der expliziten Angabe der beiden `__init__()`-Methoden ließ sich IMHO nicht vermeiden, da beim späteren Verbinden sich `connect()` andernfalls immer beschwert hatte, dass es kein `QObject` übergeben bekommt. Naja, und der Rest sollte eigentlich selbsterklärend sein.

Re: stdout "umlenken" Python3

Verfasst: Sonntag 25. November 2012, 12:18
von lunar
@snafu Leite von "QObject" und "TextIOBase" ab. "StringIO" ist keine notwendige Basisklasse, und dessen Funktionalität auch nicht nötig. Implementiere die komplette Schnittstelle, und stelle sicher, dass das Signal an jeder Stelle entsprechend ausgelöst wird.