Как инициировать событие при изменении переменной, в которую записано исключение?

Исключения, которые появляются в процессе работы программы сейчас пишутся в текстбокс окна, мне нужно, чтобы при включенном чекбоксе (log_in_DB) они писались сразу и в таблицу бд (функция log_in_sql_server, подключение к бд работает). Я пытаюсь сейчас сделать это через слоты и сигналы.

  1. источник события - изменение self.msg в классе QTextEditLogger
  2. слот это функция log_in_sql_server в классе MainWindow
class QTextEditLogger(logging.Handler):
    valueChanged = pyqtSignal(str)

    def __init__(self, parent):
        super().__init__()
        self.widget = parent.ui.plainTextEdit
        self.widget.setReadOnly(True)

    def emit(self, record):
        self.msg = self.format(record)
        self.widget.appendPlainText(self.msg)

    @property
    def msg(self):
        return self._msg

    @msg.setter
    def msg(self, value):
        self._msg = value
        self.valueChanged.emit(value)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUI()

        self.log_text_box = QTextEditLogger(self)
        self.log_text_box.setFormatter(logging.Formatter('%(asctime)s  %(module)s.%(funcName)s((lineno)d)  
                                                               %(levelname)s:%(message)s'))
        logging.getLogger().addHandler(self.log_text_box)
        logging.getLogger().setLevel(logging.DEBUG)
        self.ui.plainTextEdit.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)

        self.log_text_box.valueChanged.connect(self.log_in_sql_server)

    def initUI(self):
        self.ui.log_in_DB.clicked.connect(self.log_in_sql_server)

    def log_in_sql_server(self, msg):
        try:
            if self.ui.log_in_DB.isChecked():
                Session = db.sessionmaker()
                session = Session(bind=db.engine)
                new_post = db.UserException(message="сообщение из форматтера", 
                                            target_site="место где произошло исключение",
                                            date_time_exc='аскитайм из форматтера', 
                                            index_form=1)
                session.add(new_post)
                session.commit()
        except ValueError as e:
            logging.debug(e, exc_info=True)

Эта реализация дает ошибку: QTextEditLogger cannot be converted to PyQt5.QtCore.QObject in this context.

И еще, как после передачи self.msg разбить ее на нужные мне части? может есть что-то встроенное, потому что разбивать строку на строки между пробелами звучит не слишком хорошо.


Ответы (1 шт):

Автор решения: Alexander Chernin

Класс, использующий сигналы-слоты должен быть наследником QObject. Надо немного переделать:


import logging

class LoggingHandler(logging.Handler):
    def __init__(self, textLogger):
        super().__init__()
        self._textLogger = textLogger

    @property
    def msg(self):
        return self._msg

    @msg.setter
    def msg(self, value):
        self._msg = value
        self._textLogger.valueChanged.emit(value)

class QTextEditLogger(QObject):
    valueChanged = Signal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.handler = LoggingHandler(textLogger=self)

    def emit(self, record):
        self.handler.msg = self.handler.format(record)
        self.widget.appendPlainText(self.msg)
  

Теперь в окне:

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUI()

        self.log_text_box = QTextEditLogger(self)
        ...
        logging.getLogger().addHandler(self.log_text_box.handler)
→ Ссылка