我正在尝试根据另一个类的实例创建一个类。为此,我使用 __new__
方法:
import logging
class Logger:
def __new__(cls):
logger = logging.getLogger('main')
# make a queue in a thread to put log messages in a PyQt text browser console
return logger
def close(self):
pass
# close the thread
def main():
logger = Logger()
# more things
logger.close()
if __name__ == '__main__':
main()
我收到一个属性错误:
AttributeError: 'Logger' object has no attribute 'close'
我的想法是创建一个类来包装从logging.getLogger('main')返回的实例,并且能够调用它的原始方法(如setLevel)并添加我自己的方法。
日志记录模块的使用对于我的问题来说并不重要,但它是我不知道如何在这种情况下使用子类化的一个例子。
我的问题是:
- 出了什么问题?如何在使用
__new__
方法时完成这项工作? - 我一直想更频繁地这样做。首先这是一件愚蠢的事情吗?什么是更好的方法?
最佳答案
您可能应该将它们子类化:
from logging import Logger
def MyLogger(Logger):
def close(self):
pass
if __name__ == "__main__":
logger = MyLogger("some_name")
logger.close()
也就是说,我不知道为什么您需要手动关闭记录器。它们将在对象删除时处理自己的关闭,退出 Python 时也会发生这种情况。如果您出于某种原因想中途删除它们,则可以毫无问题地从它们自己的结构中删除它们。
<小时/>PyQt5
在评论中,OP 澄清说这适用于 PyQt5。这是我过去一年一直在使用的东西。
用于显示日志记录的小部件:
# my_package.gui.logwidget.py
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtCore import QSize
from my_package.logger import handler
class LogWidget(QTextEdit):
"""
Creates a simple textEdit widget that will automatically subscribe to the QLogger.
"""
# pylint: disable=R0903, R0201
def __init__(self, parent=None):
super().__init__(parent)
handler.recordReady.connect(self.append)
self.setReadOnly(True)
# For reasons mere mortals like me cannot imagine, to get a real Monospaced font,
# we need to set it on a font that doesn't exist.
font = QFont("MichaelMcDoesntExist")
font.setStyleHint(QFont.Monospace)
self.setFont(font)
def minimumSizeHint(self) -> QSize:
return QSize(800, 200)
实际记录器:
# my_package.logger.py
import logging
from PyQt5.QtCore import QObject, pyqtSignal
class QLogHandler(QObject, logging.Handler):
"""
QObject subclass of logging.Handler. Will emit the log messages so QObjects can listen to it to catch log
messages.
Signal:
recordReady:
Will emit a string that is the formatted log message.
"""
recordReady = pyqtSignal(str)
def emit(self, record):
self.recordReady.emit(self.format(record))
def __repr__(self):
return f"<{self.__class__.__name__} : {logging.getLevelName(self.level)}>"
handler = QLogHandler() # Global ref to connect to it's signals
Python 的内置 logging
模块已经支持线程安全日志对象,因此要让它工作,您需要的只是拥有一个日志处理程序和任意数量的日志显示小部件。
关于python - 如何使用 __new__ 创建基于另一个类的实例的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58875605/