尝试重定向stdout时无限循环

时间:2016-10-15 14:58:42

标签: python qt python-3.x pyqt

我正在尝试将stdout发送到控制台和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)

第一个回答后编辑:

我用print(message)替换了上面的行,但结果仍然相同。我将不胜感激任何帮助。

2 个答案:

答案 0 :(得分:0)

看起来您发布的代码不是您运行的代码,但假设它具有代表性,则有两个错误:必须引入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 :(得分:0)

您可以从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_())