python - 如何使用 __new__ 创建基于另一个类的实例的类?

标签 python

我正在尝试根据另一个类的实例创建一个类。为此,我使用 __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)并添加我自己的方法。

日志记录模块的使用对于我的问题来说并不重要,但它是我不知道如何在这种情况下使用子类化的一个例子。

我的问题是:

  1. 出了什么问题?如何在使用 __new__ 方法时完成这项工作?
  2. 我一直想更频繁地这样做。首先这是一件愚蠢的事情吗?什么是更好的方法?

最佳答案

您可能应该将它们子类化:

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/

相关文章:

python - 如何在文件夹中使用 opencv 更改速度后保存视频?

python - float 到 uint16 的转换会导致 numpy 中的数字增加吗?

python - 为什么我的循环每次迭代都需要更多内存?

python - Django注释过滤外键的最小值和最大值

python - 如何在 python 2.7 中将 n 个字节写入二进制文件

Python:展平函数在控制台中有效但在文件中无效?

python - 在 django 中渲染 Latex/MathJax 方程

python /Pillow : How to scale an image

python - <Key> 事件的关键代码是否与平台无关?

Python、SQLAlchemy 在 connection.execute 中传递参数