【问题标题】:Prologue and epilogue in python loggerpython logger中的序言和尾声
【发布时间】:2014-09-29 08:08:09
【问题描述】:

我希望创建一个记录器类,在第一次 logging.getLogger() 将编写一个序言,一旦该过程结束记录器并编写一个尾声

我的代码:

logger = logging.getLogger('name')
logger.info('HI')

预期输出:

2014-09-29 10:50:40,187 - INFO - ** My prologue **
2014-09-29 10:50:40,187 - INFO - HI
2014-09-29 10:50:40,187 - INFO - ** My epilogue **

【问题讨论】:

  • 用户格式化程序来获取您的日志格式
  • @Serj 你清楚他只需要每个记录器的序言和结语一次,而不是每条消息吗? AIUI,格式化程序是每个消息的东西......

标签: python logging


【解决方案1】:

正如观察到的,我之前的答案中的 EpiLogger 不是“单例”,必须在要使用它们的模块之间传递。

解决此问题的选项包括

  • 子类化 logger.Logger(如果这实际上是可能的,我没有调查过),
  • 实现一种机制来创建、存储和检索像 logger.getLogger 这样的 EpiLogger(可笑的夸大其词)
  • 创建可在多个模块中使用的类似单例的 EpiLogger。

这个解决方案是后者。

import logging

class epiLogger():
    _initialised = {}
    _finalised = {}

    def __init__(self, name):
        self.logger = logging.getLogger(name)
        self.name = name
        if not epiLogger._initialised.get(name):
            self.logger.addHandler(logging.StreamHandler())
            self.logger.setLevel(logging.INFO)
            self.logger.info('** My Prologue **')
            epiLogger._initialised[self.name] = True

    def info(self, the_info):
        self.logger.info(the_info)

    def __del__(self):
        if not self.__class__._finalised.get(self.name):
            self.logger.info('** My Epilogue **')
            self.__class__._finalised[self.name] = True

a = epiLogger("foo")

a.info("foo!")
a.info("bar!")
a.info("party!")

我知道这样做感觉不错,但请阅读此处:http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/。我会认真地问自己“实际上,从长远来看,最好将每个 EpiLogger 传递到它所属的地方吗?”

当然还有investigate subclassing logger.Logger :)

【讨论】:

  • 我试过这个,由于某种原因它并不总是记录结尾。不过,我确实喜欢关于单身人士的链接,并决定用不同的方法解决这个问题
  • 还不知道为什么会这样,但我很快就编码了,只做了一个简单的测试。当我有时间时,我可能会出于好奇而修补。我的大部分 python 都在构建 wx 应用程序,我明确地将我的记录器传递给视图和控制器。
  • 在专家的帮助下 (stackoverflow.com/a/26119248/554807) 我想我已经找到了会给你带来冲突的原因,并进行了相应的编辑。我对其进行了更彻底的测试(多个文件,多个记录器)。我很想知道它是否适用于您的情况。即使现在代码更加诡异 :) 这对你来说是单例 ;)
【解决方案2】:

这是一个蛮力,简单的实现。

请注意,您要在 EpiLogger 上调用的任何 logging.Logger 方法都需要实现:我只实现了 info()。

import logging

# class definition for the new logger that does the pro and epilogues

class epiLogger():
    def __init__(self, name):
        self.logger = logging.getLogger(name)
        self.logger.info('** My Prologue **')

    def info(self, the_info):
        self.logger.info(the_info)

    def __del__(self):
        self.logger.info('** My Epilogue **')

# preamble to set up the underlying logger that it needs
# ... could be inside the class constructor, depending on whether the class
# is supposed to be "encapsulating and providing"  or "using" this external one

the_logger = logging.getLogger("foo")
the_logger.setLevel(logging.INFO)

the_logger.addHandler(logging.StreamHandler())

# using the good stuff...

a = epiLogger("foo")

a.info("foo!")
a.info("bar!")
a.info("party!")

产生:

~ mgregory$ python foo.py
** My Prologue **
foo!
bar!
party!
** My Epilogue **
~ mgregory$ 

(为简单起见,我省略了时间/日期格式等,因为它与问题并不真正相关)

【讨论】:

  • 如何从其他模块获取Logger?似乎我必须将 EpiLogger 的实例传递给我的所有模块
  • 我添加了一个单独的答案,因为这是一个......不同的答案:)
猜你喜欢
  • 2021-12-21
  • 1970-01-01
  • 2013-03-17
  • 2017-07-01
  • 2019-11-25
  • 1970-01-01
  • 1970-01-01
  • 2021-02-02
  • 1970-01-01
相关资源
最近更新 更多