【问题标题】:Python: do I need a Singleton?Python:我需要一个单例吗?
【发布时间】:2020-04-30 13:36:52
【问题描述】:

我在logger.py 中有多个实例化的记录器类,我将它们导入到多个其他模块中。

logger.py

class Logger:
    def __init__(self, name='default'):
        # create a Logger with custom handlers
        # ...

main_logger = Logger('main_logger')
another_topic_logger = Logger('another_topic_logger')

module_a.py

from logger import main_logger
main_logger.info('hello!')

Python 如何在后台处理它?我需要一个单例包装器还是这样就可以了?

【问题讨论】:

  • 你并不能真正告诉人们,“这个问题是有话题的”。这完全取决于阅读问题的人。我已经删除了那部分,因为我认为它可能会让人们对你的问题产生偏见。
  • 您可以尝试在模块中使用id(main_logger) 来查看您是否使用相同的实例。通常 Python 会记住导入的模块,它不会再次导入它,但它使用了已导入的代码 - 但我不确定如果你在其他模块中导入相同的模块是否属实。
  • 也许我被这个名字误导了,但你为什么要定义自己的 Logger 类而不是使用 logging 模块? (顺便说一下,这不会让你直接实例化 its Logger 类;你调用一个名为 getLogger 的模块级函数,它会根据参数创建一个新实例或返回现有实例。)
  • @larsks 这并不是要决定一个意见,而是要澄清我在问这个问题之前考虑过这个问题,因为它很容易被误解。
  • 另外,您有多个 Logger 类实例;仅导入其中一个实例的另一个模块不会使任何东西成为单例。

标签: python python-3.x oop design-patterns


【解决方案1】:

这很好。但是为什么需要不同的记录器类呢?

在python中,不同的记录器可以是同一个类的实例,具有不同的记录器名称。

参考https://docs.python.org/3/howto/logging-cookbook.html

您可以为不同的日志实例设置不同的处理程序。

通常,我们以这种方式创建和使用记录器:

module_a.py

import logging
logger = logging.getLogger('module_a')
fh = logging.FileHandler('spama.log')
logger.addHandler(fh)

Class foo:
    pass

module_b.py

import logging
logger = logging.getLogger('module_b')
fh = logging.FileHandler('spamb.log')
logger.addHandler(fh)

Class bar:
    pass

如果你想在一个文件中配置很多记录器:

log_config.py

# You could create your loggers anywhere, but configure them in one file

import logging.config


LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'filters': {
        'special': {
            '()': 'project.logging.SpecialFilter',
            'foo': 'bar',
        }
    },
    'handlers': {
        'null': {
            'level':'DEBUG',
            'class':'django.utils.log.NullHandler',
        },
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
            'formatter': 'simple'
        },
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
            'filters': ['special']
        }
    },
    'loggers': {
        'module_a': {
            'handlers':['null'],
            'propagate': True,
            'level':'INFO',
        },
        'module_b': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': False,
        },
        'myproject.custom': {
            'handlers': ['console', 'mail_admins'],
            'level': 'INFO',
            'filters': ['special']
        }
    }
}

logging.config.dictConfig(LOGGING)

ma​​in.py

import module_a
import module_b
import log_config

module_a.logger.debug("something")

顺便说一句,如果您在不同的 python 文件中获得具有相同名称的记录器,它们就是完全相同的实例。其实getLogger函数就是get or create a logger with the given name

【讨论】:

  • 谢谢!我有多个 logging.getLogger() 使用不同的处理程序,具体取决于主题。有些日志文件允许增长到 10 MB,有些只允许增长到 1 MB。有些保存debug() 输出,有些则不保存。我的目标是在一个文件中一次性完成所有这些配置。
  • @Mr.B.哦,我知道你想要什么,等一下,或者看看docs.python.org/3/howto/…
猜你喜欢
  • 1970-01-01
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
相关资源
最近更新 更多