日志记录发射函数和 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()
我试图在每次调用日志记录处理程序发出函数时发送一个 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()