Бесконечный цикл при попытке перенаправить стандартный вывод

#python #qt #python-3.x #pyqt

#python #qt #python-3.x #pyqt

Вопрос:

Я пытаюсь отправить стандартный вывод как на консоль, так и QTextBrowser на виджет. Но я получаю какой-то бесконечный цикл, а затем приложение завершает работу.

Вот мой код:

 import sys
from PyQt5 import QtWidgets, uic
from PyQt5.QtCore import *

qtCreatorFile = "qt_ui.ui"
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        self.start_button.clicked.connect(printing)

def printing():
    print("Pressed!n")

class Logger(QObject):
    def __init__(self):
        super().__init__()
        self.terminal = sys.stdout

    def write(self, message):
        self.terminal.write(message)
        self.log_browser.setText(message) #problem is in this line

    def flush(self):
        pass

if __name__ == "__main__":
    sys.stdout = Logger()
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
 

В результате при нажатии кнопки start_button наблюдается следующее:

 "C:...python.exe" "E:/.../qt_gui.py"
Pressed!
Pressed!
Pressed!
... (totaly 332 times)
Pressed!
Pressed!
Pressed!

Process finished with exit code 1
 

Я просто не могу понять, почему эта строка создает цикл:

 self.log_browser.setText(message)
 

Редактировать после 1-го ответа:

Я заменил строку выше на print(message) , но все равно получаю те же результаты. Я был бы признателен за любую помощь.

Комментарии:

1. В определении класса ошибка отступа

2. Это была ошибка копирования / вставки, а не из исходного кода. Я исправил это.

Ответ №1:

Вы можете выдать пользовательский сигнал Logger и подключить его к обозревателю журналов:

 class Logger(QObject):
    loggerMessage = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.terminal = sys.stdout

    def write(self, message):
        self.terminal.write(message)
        self.loggerMessage.emit(message)

    def flush(self):
        pass

if __name__ == "__main__":

    sys.stdout = Logger()
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    sys.stdout.loggerMessage.connect(window.log_browser.insertPlainText)
    window.show()
    sys.exit(app.exec_())
 

Комментарии:

1. Я пробовал этот код, но сообщения не отображаются в QTextBrowser. Есть предложения, почему?

2.@dandepeched. Кажется, что print запись выполняется stdout дважды — один раз для текста и один раз для конечной строки. Поэтому, если вы используете setText , второй сигнал перезапишет первый. Я изменил свой пример для использования insertPlainText , поэтому вместо этого он добавляет все сообщения.

Ответ №2:

Похоже, что опубликованный вами код не является кодом, который вы запустили, но, предполагая, что он репрезентативен, возникают две ошибки: базовый класс Logger должен быть инициализирован, а self.log_browser нигде не определен. Но это не вызывает цикла, приложение завершает работу (потому что есть исключение, но нет исключения, см. ). Поскольку я не знаю, каким должен быть log_browser, я определил его как Mock() (из unittest.mock), который примет все, что с ним сделано, и проблема исчезнет.

 class Logger(QObject):
    def __init__(self):
        super().__init__()
        self.terminal = sys.stdout
        from unittest.mock import Mock
        self.log_browser = Mock()

    def write(self, message):
        self.terminal.write(message)
        self.log_browser.setText(message) # problem was this line

    def flush(self):
        pass
 

Комментарии:

1. log_browser определен в файле «qt_ui.ui», который переведен uic.

2. self.log_browser = QtWidgets. QTextBrowser(self.centralwidget)

3. Я упростил код, заменив log_browser функцией печати, также инициализировал класс, как вы сказали, но все равно получаю то же поведение.

4. Вызов print() из метода write() снова вызовет write(), что приведет к рекурсии, пока в интерпретаторе Python не закончится пространство стека.