I have a program in Python with PyQt, designed to run on Windows. This program makes a lot of operations and prints a lot of info. But as I want to freeze it and don't want the prompt screen to appear, I want that all that info appears in the main application, in a QTextEdit or so. How can i make the program work so it gets the output from the interpreter and shows it on the textEdit at the same time, just like it does on the real interpreter?
5 Answers
I assume that with "output from the interpreter", you mean output written to the console or terminal window, such as output produced with print()
.
All console output produced by Python gets written to the program's output streams sys.stdout
(normal output) and sys.stderr
(error output, such as exception tracebacks). These are file-like objects.
You can replace these streams with your own file-like object. All your custom implementation must provide is a write(text)
function. By providing your own implementation, you can forward all output to your widget:
class MyStream(object):
def write(self, text):
# Add text to a QTextEdit...
sys.stdout = MyStream()
sys.stderr = MyStream()
If you ever need to reset these streams, they are still available as sys.__stdout__
and sys.__stderr__
:
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
Update
Here is some working code for PyQt4. First define a stream that reports data written to it with a Qt signal:
from PyQt4 import QtCore
class EmittingStream(QtCore.QObject):
textWritten = QtCore.pyqtSignal(str)
def write(self, text):
self.textWritten.emit(str(text))
Now, in your GUI, install an instance of this stream to sys.stdout
and connect the textWritten
signal to a slot that writes the text to a 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()

- 64,979
- 15
- 154
- 145
-
1I liked your suggestion. Seems really easy to implement. But do I need to create e new class for it? I mean, can i just create the write function in the same class of my main window? – jonathan.hepp Dec 02 '11 at 12:53
-
@dex19dt: You certainly could, but I would advice against it as it violates the single responsibility principle. In my code, I created a stream class that subclasses `QObject` and has a `textWritten` signal emitted by `write()`. I then just connect this signal with a slot in my window that appends the text to a `QTextEdit`. Advantage: I can format normal output and error output differently; latter uses a red text color. – Ferdinand Beyer Dec 02 '11 at 13:03
-
Ok. So i created another file named stream.py and paste the code you wrote. I imported it in the main program and it raises no errors but it doesnt insert the text in the textEdit widget either. My write function is simply `self.textEdit.append(str(text))` Is it wrong? – jonathan.hepp Dec 02 '11 at 13:18
-
@dex19dt: You seem to have a bug somewhere. I suggest that you leave alone `sys.stderr` for now and just try to capture `sys.stdout`. This way, any exceptions in your stream code will show up as usual. In fact, if your `write()` function raises an exception, you could run into an infinite loop! – Ferdinand Beyer Dec 02 '11 at 13:39
-
I created another file named stream.py and paste your code there. I imported it in the main program but it wont show the text on the textEdit widget. My write function is this `self.textEdit.append(str(text))` and I know that's not right. How can I reach the textEdit which is in another class of another file? P.S. Yes i removed the stderr part, thanks. – jonathan.hepp Dec 02 '11 at 13:40
-
@dex19dt: See my updated answer for an example of how to use this technique in a nice decoupled way! – Ferdinand Beyer Dec 02 '11 at 14:20
-
Is there a way to dynamically append text to the widget in this solution ? That is , each time a print statement prints the widget is updated and not all output appears at one go. – CosmoSurreal Sep 26 '12 at 11:10
-
@CosmoSurreal: Please use the 'ask question' option to ask follow-up questions. You can refer to this answer in your new question. By the way, the suggested solution _does_ append text to the widget... – Ferdinand Beyer Sep 26 '12 at 11:33
-
@FerdinandBeyer: In Python3.3, it raises the `AttributeError` although it ignores it. `Exception AttributeError: "'EmittingStream' object has no attribute 'flush'" in <__main__.EmittingStream object at 0xb4f6af14> ignored`. See the [doc for `print()` in Python 3.3](http://docs.python.org/3.3/library/functions.html?highlight=print#print), a new keyword argument was added. Could you please update the answer taking this into consideration. Thanks! – Aditya Apr 15 '13 at 20:50
-
@FerdinandBeyer: Thanks for giving the direction. I would try to solve this riddle and update here :-) – Aditya Apr 16 '13 at 09:11
Unfortunatelly the example doesn't work with PySide. It gives the following error:
sys.stdout = EmittingStream(textWritten=self.write2Console)
AttributeError: 'textWritten()' is not a Qt property or a signal
We need to make the following changes for it to work with PySide:
sys.stdout = EmittingStream()
self.connect(sys.stdout,QtCore.SIGNAL('textWritten(QString)'),self.write2Console)
-
1According to the [new sintax](http://qt-project.org/wiki/Signals_and_Slots_in_PySide), that would be `sys.stdout.textWritten.connect(self.write2Console)` – iled Sep 10 '14 at 14:49
I suggest you use the logging library. http://docs.python.org/library/logging.html You could write your own log handler for communicating with the QTextEdit. Here's a nice tutorial which will get you started: http://pantburk.info/?blog=77

- 2,209
- 19
- 26
I posted some stuff for a terminal application for PySide on this a while back Terminal like app in PySide. If You are looking at PyQt then check for PySide as well. They are basically the same thing except for licensing and a few differences in syntax.
Thank you Ferdinand and Tommy. I have posted my new window solution for PySide6, since this thread comes up often in searches. I wanted to create a "loading" window when I have a QThread doing a bunch of stuff in the background. I create this window when I start the thread and then connect .close() from the completion of the thread. I got the closeEvent idea from a different SO Q&A. I can run my GUI from a Windows terminal, see the usual stdout in the terminal, call my loading thread function, the window pops up, the stdout goes to the window, then when it is done the window closes and the stdout returns to the terminal.
class StdOutWindow(QtWidgets.QWidget):
def __init__(self):
super(StdOutWindow, self).__init__()
layout = QtWidgets.QVBoxLayout()
self.setWindowTitle('Loading Data')
self.txt_edit = QtWidgets.QTextEdit()
layout.addWidget(self.txt_edit)
self.setLayout(layout)
self.setMinimumSize(600, 300)
sys.stdout = EmittingStream()
sys.stdout.text_written.connect(self.normal_output_written)
def closeEvent(self, event: QtGui.QCloseEvent) -> None:
sys.stdout = sys.__stdout__
event.accept()
def normal_output_written(self, text):
cursor = self.txt_edit.textCursor()
cursor.movePosition(QtGui.QTextCursor.End)
cursor.insertText(text)
self.txt_edit.setTextCursor(cursor)
self.txt_edit.ensureCursorVisible()
class EmittingStream(QtCore.QObject):
text_written = QtCore.Signal(str)
def write(self, text):
self.text_written.emit(str(text))

- 131
- 1
- 6