python logging output on both GUI and console

2020-07-23 08:27发布

问题:

Given this little snippet:

import sys
import os
import logging
from PyQt5 import QtGui, QtWidgets, QtCore

log = logging.getLogger("Foo")
logging.basicConfig(
    level=logging.INFO, format='%(levelname)s: %(filename)s - %(message)s')
log.setLevel(logging.DEBUG)


class ConsolePanelHandler(logging.Handler):

    def __init__(self, parent):
        logging.Handler.__init__(self)
        self.parent = parent

    def emit(self, record):
        self.parent.write(self.format(record))


class Foo(QtWidgets.QWidget):

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)

        self.textEdit = QtWidgets.QTextEdit(self)
        self.textEdit.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
        self.textEdit.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)

        vbox = QtWidgets.QVBoxLayout()
        self.setLayout(vbox)
        vbox.addWidget(self.textEdit)

    def write(self, s):
        self.textEdit.setFontWeight(QtGui.QFont.Normal)
        self.textEdit.append(s)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    console_panel = Foo()
    handler = ConsolePanelHandler(console_panel)
    log.addHandler(handler)

    log.info("Getting logger {0} - {1}".format(id(log), log.handlers))
    [log.debug("This is normal text " + str(i)) for i in range(5)]
    console_panel.show()

    sys.exit(app.exec_())

Questions:

  • Why is log writing to both the console and gui? As far as i know log.handlers len should be only 1.
  • How can i write only to the gui supressing the console messages?
  • Why the gui format is not the one specified by basicConfig?

回答1:

Your problem is caused by calling basicConfig() at import time - as documented, this adds a console logger to the root logger if it doesn't have any handlers already.

You need to remove this call and add a line in the if __name__ == '__main__' clause:

handler.setFormatter(logging.Formatter('%(levelname)s: %(filename)s - %(message)s'))

and you should then get the result you were expecting.

The reason you saw both messages is because how information flows between loggers and handlers, which is described in the documentation here.