日志记录发射函数和 QT 发射信号之间的名称冲突

Conflicting names between logging emit function and QT emit signal

我试图在每次调用日志记录处理程序发出函数时发送一个 Qt 信号。但我认为 MyLogHandler.emit 和 log.emit 功能是冲突的。

from PySide2.QtCore import QObject, Signal
import logging

class MyLogHandler(logging.Handler, QObject):
    log = Signal(str)

    def emit(self, record):
        self.log.emit('send')

if __name__ == "__main__":
    logging.getLogger().addHandler(MyLogHandler())
    logging.warning('logging test')

错误:

TypeError: emit() takes 2 positional arguments but 3 were given

更新:

我已经尝试使用组合(根据@eyllanesc),但我仍然无法将信号连接到 QML 文件。我不确定为什么我无法在 QML 中接收到信号。它似乎没有发出任何东西。我做错了什么?

from functools import cached_property
import logging
import sys

from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QCoreApplication, QObject, QTimer, Signal, QUrl

class Main(QObject):
    log = Signal(str)


class Log(object):
    def __init__(self):
        logging.basicConfig(
            level=logging.DEBUG,
            format="%(asctime)s [%(levelname)s] %(message)s",
            handlers=[
                logging.FileHandler("debug.log", mode='w'),
                logging.StreamHandler(),
                MyLogHandler()
            ]
        )

class MyLogHandler(logging.Handler):
    @cached_property
    def main(self):
        return Main()

    def emit(self, record):
        msg = self.format(record)
        self.main.log.emit(msg)


if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    main = Main()

    Log()

    QTimer.singleShot(1000, lambda: logging.warning("logging test"))
    engine.rootContext().setContextProperty("main", main)
    engine.load(QUrl("Main3.qml"))
    app.exec_()

QML:Main3.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window {
    width: 500
    height: 500
    visible: true
    title: qsTr("MIST")

    Text {
        id: text
        anchors.fill: parent

    }

    Connections {
        target: main

        function onLog(msg) {
            text.text = msg
        }

    }
}

问题是两个基 类 都有一个导致冲突的 emit() 方法。解决方法是不使用继承,而是使用组合:

from functools import cached_property
import logging

from PySide2.QtCore import QCoreApplication, QObject, QTimer, Signal


class Bridge(QObject):
    log = Signal(str)


class MyLogHandler(logging.Handler):
    @cached_property
    def bridge(self):
        return Bridge()

    def emit(self, record):
        msg = self.format(record)
        self.bridge.log.emit(msg)


if __name__ == "__main__":
    app = QCoreApplication()

    handler = MyLogHandler()
    handler.bridge.log.connect(print)

    logging.getLogger().addHandler(handler)

    QTimer.singleShot(1000, lambda: logging.warning("logging test"))
    QTimer.singleShot(2000, QCoreApplication.quit)

    app.exec_()

更新:

import logging
import sys

from PySide2.QtCore import QObject, QTimer, QUrl, Signal
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine


class Main(QObject):
    log = Signal(str)


class QLogHandler(logging.Handler):
    def __init__(self, emitter):
        super().__init__()
        self._emitter = emitter

    @property
    def emitter(self):
        return self._emitter

    def emit(self, record):
        msg = self.format(record)
        self.emitter.log.emit(msg)


def configure_logging(*, handlers):
    logging.basicConfig(
        level=logging.DEBUG,
        format="%(asctime)s [%(levelname)s] %(message)s",
        handlers=handlers,
    )


def main():
    app = QGuiApplication()

    main = Main()

    configure_logging(
        handlers=[
            logging.FileHandler("debug.log", mode="w"),
            logging.StreamHandler(),
            QLogHandler(main),
        ]
    )

    engine = QQmlApplicationEngine()
    engine.rootContext().setContextProperty("main", main)
    engine.load(QUrl("Main3.qml"))

    QTimer.singleShot(1000, lambda: logging.warning("logging test"))

    ret = app.exec_()
    sys.exit(ret)


if __name__ == "__main__":
    main()