Wie erfasst man die Ausgabe des Python-Interpreters und zeigt sie in einem Text-Widget an?

Lesezeit: 4 Minuten

Ich habe ein Programm in Python mit PyQt, das für die Ausführung unter Windows entwickelt wurde. Dieses Programm macht viele Operationen und druckt viele Informationen. Aber da ich es einfrieren möchte und nicht möchte, dass der Eingabeaufforderungsbildschirm angezeigt wird, möchte ich, dass alle diese Informationen in der Hauptanwendung, in einem QTextEdit oder so, angezeigt werden. Wie kann ich das Programm so arbeiten lassen, dass es die Ausgabe vom Interpreter erhält und sie gleichzeitig auf dem TextEdit anzeigt, genau wie auf dem echten Interpreter?

Wie erfasst man die Ausgabe des Python Interpreters und zeigt sie
Ferdinand Beyer

Ich gehe davon aus, dass Sie mit “Ausgabe vom Interpreter” eine Ausgabe meinen, die an die Konsole oder das Terminalfenster geschrieben wird, z. B. eine Ausgabe, die mit erstellt wurde print().

Alle von Python erzeugten Konsolenausgaben werden in die Ausgabeströme des Programms geschrieben sys.stdout (normale Ausgabe) und sys.stderr (Fehlerausgabe, wie z. B. Exception-Tracebacks). Dies sind dateiähnliche Objekte.

Sie können diese Streams durch Ihr eigenes dateiähnliches Objekt ersetzen. Alles, was Ihre benutzerdefinierte Implementierung bereitstellen muss, ist a write(text) Funktion. Indem Sie Ihre eigene Implementierung bereitstellen, können Sie alle Ausgaben an Ihr Widget weiterleiten:

class MyStream(object):
    def write(self, text):
        # Add text to a QTextEdit...

sys.stdout = MyStream()
sys.stderr = MyStream()

Wenn Sie diese Streams jemals zurücksetzen müssen, sind sie weiterhin als verfügbar sys.__stdout__ und sys.__stderr__:

sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__

Aktualisieren

Hier ist ein funktionierender Code für PyQt4. Definieren Sie zuerst einen Stream, der Daten meldet, die mit einem Qt-Signal in ihn geschrieben wurden:

from PyQt4 import QtCore

class EmittingStream(QtCore.QObject):

    textWritten = QtCore.pyqtSignal(str)

    def write(self, text):
        self.textWritten.emit(str(text))

Installieren Sie nun in Ihrer GUI eine Instanz dieses Streams in sys.stdout und verbinde die textWritten Signal an einen Slot, der den Text an a schreibt QTextEdit:

# Within your main window class...

def __init__(self, parent=None, **kwargs):
    # ...

    # Install the custom output stream
    sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)

def __del__(self):
    # Restore sys.stdout
    sys.stdout = sys.__stdout__

def normalOutputWritten(self, text):
    """Append text to the QTextEdit."""
    # Maybe QTextEdit.append() works as well, but this is how I do it:
    cursor = self.textEdit.textCursor()
    cursor.movePosition(QtGui.QTextCursor.End)
    cursor.insertText(text)
    self.textEdit.setTextCursor(cursor)
    self.textEdit.ensureCursorVisible()

  • Ich mochte Ihren Vorschlag. Scheint wirklich einfach umzusetzen. Aber muss ich dafür eine neue Klasse erstellen? Ich meine, kann ich die Schreibfunktion einfach in derselben Klasse meines Hauptfensters erstellen?

    – jonathan.hepp

    2. Dezember 11 um 12:53 Uhr

  • @dex19dt: Das könntest du sicherlich, aber ich würde davon abraten, da es gegen das Prinzip der Einzelverantwortung verstößt. In meinem Code habe ich eine Stream-Klasse erstellt, die Unterklassen erstellt QObject und hat ein textWritten Signal ausgesendet von write(). Dieses Signal verbinde ich dann einfach mit einem Slot in meinem Fenster, der den Text an a anhängt QTextEdit. Vorteil: Ich kann normale Ausgabe und Fehlerausgabe unterschiedlich formatieren; letzteres verwendet eine rote Textfarbe.

    – Ferdinand Beyer

    2. Dezember 11 um 13:03 Uhr

  • In Ordnung. Also habe ich eine weitere Datei namens stream.py erstellt und den von Ihnen geschriebenen Code eingefügt. Ich habe es in das Hauptprogramm importiert und es löst keine Fehler aus, aber es fügt den Text auch nicht in das TextEdit-Widget ein. Meine Schreibfunktion ist einfach self.textEdit.append(str(text)) Ist es falsch?

    – jonathan.hepp

    2. Dezember 11 um 13:18 Uhr


  • @dex19dt: Du scheinst irgendwo einen Fehler zu haben. Ich schlage vor, dass Sie in Ruhe gehen sys.stderr für jetzt und versuchen Sie einfach zu erfassen sys.stdout. Auf diese Weise werden alle Ausnahmen in Ihrem Stream-Code wie gewohnt angezeigt. In der Tat, wenn Ihre write() -Funktion eine Ausnahme auslöst, könnten Sie in eine Endlosschleife geraten!

    – Ferdinand Beyer

    2. Dezember 11 um 13:39 Uhr


  • Ich habe eine weitere Datei namens stream.py erstellt und Ihren Code dort eingefügt. Ich habe es in das Hauptprogramm importiert, aber es zeigt den Text nicht im TextEdit-Widget an. Meine Schreibfunktion ist diese self.textEdit.append(str(text)) und ich weiß, dass das nicht stimmt. Wie kann ich das textEdit erreichen, das sich in einer anderen Klasse einer anderen Datei befindet? PS Ja, ich habe den Stderr-Teil entfernt, danke.

    – jonathan.hepp

    2. Dezember 11 um 13:40 Uhr


1642812365 195 Wie erfasst man die Ausgabe des Python Interpreters und zeigt sie
TommyX

Leider funktioniert das Beispiel nicht mit PySide. Es gibt den folgenden Fehler:

sys.stdout = EmittingStream(textWritten=self.write2Console)
AttributeError: 'textWritten()' is not a Qt property or a signal

Wir müssen die folgenden Änderungen vornehmen, damit es mit PySide funktioniert:

sys.stdout = EmittingStream()
self.connect(sys.stdout,QtCore.SIGNAL('textWritten(QString)'),self.write2Console)

  • Laut der neue Syntax, das wäre sys.stdout.textWritten.connect(self.write2Console)

    – ich führe

    10. September 14 um 14:49 Uhr

Ich schlage vor, Sie verwenden die Protokollierungsbibliothek. http://docs.python.org/library/logging.html
Sie könnten Ihren eigenen Log-Handler für die Kommunikation mit QTextEdit schreiben. Hier ist ein nettes Tutorial, das Ihnen den Einstieg erleichtern wird: http://pantburk.info/?blog=77

1642812366 171 Wie erfasst man die Ausgabe des Python Interpreters und zeigt sie
Engel

Ich habe vor einiger Zeit einige Sachen für eine Terminalanwendung für PySide auf dieser Terminal-ähnlichen App in PySide gepostet. Wenn Sie sich PyQt ansehen, suchen Sie auch nach PySide. Sie sind im Grunde dasselbe, abgesehen von der Lizenzierung und einigen Unterschieden in der Syntax.

.

583020cookie-checkWie erfasst man die Ausgabe des Python-Interpreters und zeigt sie in einem Text-Widget an?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy