Ведение журнала PyQt5 в реальном времени в QTextedit из-за пределов основного модуля

Мне потребовалось много времени, чтобы опубликовать здесь свой первый вопрос, так как все ответы на все вопросы, которые у меня были в прошлом, уже здесь. Но я еще не нашел решения этой проблемы, так что начнем:

ОПИСАНИЕ: В моем приложении я хочу отображать информацию журнала в реальном времени в виджете QTextEdit. Чтобы заставить это работать, я реализовал решение, которое нашел здесь.

ПРОБЛЕМА: Код в приведенной выше ссылке работает как шарм, пока все выполняемые функции являются частью основного класса Window. Но для моего приложения мне нужно, чтобы это работало вне основного модуля. Я хочу иметь возможность получать информацию журнала в реальном времени (строка за строкой) из внешних функций (например: когда функция «someProcess» находится в другом модуле, см. код ниже). Когда я пытаюсь это сделать, все работает, но он не отображает строку информации журнала на строку, как это было раньше, а все строки сразу после завершения внешней функции.

Я предполагаю, что это логично, потому что во внешней функции нет сигнала, исходящего от объекта логгера во внешнем модуле. Но я не могу обдумать простой (или любой) способ сделать это.

main.py

import sys
import time
import logging
import othermodule as om
from PyQt5.QtCore import QObject, pyqtSignal, QThread
from PyQt5.QtWidgets import QWidget, QTextEdit, QPushButton, QVBoxLayout, QApplication

logger = logging.getLogger(__name__)


class ConsoleWindowLogHandler(logging.Handler, QObject):
    sigLog = pyqtSignal(str)
    def __init__(self):
        logging.Handler.__init__(self)
        QObject.__init__(self)

    def emit(self, logRecord):
        message = str(logRecord.getMessage())
        self.sigLog.emit(message)


class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        # Layout
        textBox = QTextEdit()
        textBox.setReadOnly(True)
        self.button = QPushButton('Click')
        vertLayout = QVBoxLayout()
        vertLayout.addWidget(textBox)
        vertLayout.addWidget(self.button)
        self.setLayout(vertLayout)

        # Connect button
        
        self.button.clicked.connect(self.buttonPressed)

        # Thread
        self.bee = Worker(self.test, ())
        self.bee.finished.connect(self.restoreUi)
        self.bee.terminate()

        # Console handler
        consoleHandler = ConsoleWindowLogHandler()
        consoleHandler.sigLog.connect(textBox.append)
        logger.addHandler(consoleHandler)

    def buttonPressed(self):
        self.button.setEnabled(False)
        self.bee.start()

    def restoreUi(self):
        self.button.setEnabled(True)

    def test(self):
        logger.error('Starting')
        om.someProcess()

class Worker(QThread):
    def __init__(self, func, args):
        super(Worker, self).__init__()
        self.func = func
        self.args = args

    def run(self):
        self.func(*self.args)


def main():
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

другоймодуль.py

import time
import logging

logger = logging.getLogger(__name__)

def someProcess(self):
    logger.error("starting")
    for i in range(10):
        logger.error("line%d" % i)  # Every iteration, I want to display this line per line 
                                    # in the textbox on the main window
        time.sleep(2)    # in my own code, here comes a time consuming task 
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
908
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ошибка вызвана тем, что ConsoleWindowLogHandler обрабатывает только информацию регистратора, созданного в main.py, но не информацию, созданную в othermodule.py, решение состоит в том, чтобы назначить ConsoleWindowLogHandler также обработчиком регистратора, созданного в othermodule.py:

# Console handler
consoleHandler = ConsoleWindowLogHandler()
consoleHandler.sigLog.connect(textBox.append)
logger.addHandler(consoleHandler)
om.logger.addHandler(consoleHandler)

Note: Although it is trivial you should change def someProcess(self): to def someProcess():

Другие вопросы по теме