Best way to display logs in pyqt? Best way to display logs in pyqt? python python

Best way to display logs in pyqt?


Adapted from Todd Vanyo's example for PyQt5:

import sysfrom PyQt5 import QtWidgetsimport logging# Uncomment below for terminal log messages# logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(name)s - %(levelname)s - %(message)s')class QTextEditLogger(logging.Handler):    def __init__(self, parent):        super().__init__()        self.widget = QtWidgets.QPlainTextEdit(parent)        self.widget.setReadOnly(True)    def emit(self, record):        msg = self.format(record)        self.widget.appendPlainText(msg)class MyDialog(QtWidgets.QDialog, QtWidgets.QPlainTextEdit):    def __init__(self, parent=None):        super().__init__(parent)        logTextBox = QTextEditLogger(self)        # You can format what is printed to text box        logTextBox.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))        logging.getLogger().addHandler(logTextBox)        # You can control the logging level        logging.getLogger().setLevel(logging.DEBUG)        self._button = QtWidgets.QPushButton(self)        self._button.setText('Test Me')        layout = QtWidgets.QVBoxLayout()        # Add the new logging box widget to the layout        layout.addWidget(logTextBox.widget)        layout.addWidget(self._button)        self.setLayout(layout)        # Connect signal to slot        self._button.clicked.connect(self.test)    def test(self):        logging.debug('damn, a bug')        logging.info('something to remember')        logging.warning('that\'s not right')        logging.error('foobar')app = QtWidgets.QApplication(sys.argv)dlg = MyDialog()dlg.show()dlg.raise_()sys.exit(app.exec_())


If you are using the Python logging module to can easily create a custom logging handler that passes the log messages through to a QPlainTextEdit instance (as described by Christopher).

To do this you first subclass logging.Handler. In this __init__ we create the QPlainTextEdit that will contain the logs. The key bit here is that the handle will be receiving messages via the emit() function. So we overload this function and pass the message text into the QPlainTextEdit.

import loggingclass QPlainTextEditLogger(logging.Handler):    def __init__(self, parent):        super(QPlainTextEditLogger, self).__init__()        self.widget = QPlainTextEdit(parent)        self.widget.setReadOnly(True)    def emit(self, record):        msg = self.format(record)        self.widget.appendPlainText(msg)    def write(self, m):        pass

Create an object from this class, passing it the parent for the QPlainTextEdit (e.g. the main window, or a layout). You can then add this handler for the current logger.

# Set up logging to use your widget as a handlerlog_handler = QPlainTextEditLogger(<parent widget>)logging.getLogger().addHandler(log_handler)


Here's a complete working example based on mfitzp's answer:

import sysfrom PyQt4 import QtCore, QtGuiimport logging# Uncomment below for terminal log messages# logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(name)s - %(levelname)s - %(message)s')    class QPlainTextEditLogger(logging.Handler):    def __init__(self, parent):        super().__init__()        self.widget = QtGui.QPlainTextEdit(parent)        self.widget.setReadOnly(True)        def emit(self, record):        msg = self.format(record)        self.widget.appendPlainText(msg)    class MyDialog(QtGui.QDialog, QPlainTextEditLogger):    def __init__(self, parent=None):        super().__init__(parent)            logTextBox = QPlainTextEditLogger(self)        # You can format what is printed to text box        logTextBox.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))        logging.getLogger().addHandler(logTextBox)        # You can control the logging level        logging.getLogger().setLevel(logging.DEBUG)        self._button = QtGui.QPushButton(self)        self._button.setText('Test Me')            layout = QtGui.QVBoxLayout()        # Add the new logging box widget to the layout        layout.addWidget(logTextBox.widget)        layout.addWidget(self._button)        self.setLayout(layout)            # Connect signal to slot        self._button.clicked.connect(self.test)        def test(self):        logging.debug('damn, a bug')        logging.info('something to remember')        logging.warning('that\'s not right')        logging.error('foobar')if (__name__ == '__main__'):    app = None    if (not QtGui.QApplication.instance()):        app = QtGui.QApplication([])    dlg = MyDialog()    dlg.show()    dlg.raise_()    if (app):        app.exec_()