繁体   English   中英

Python日志记录:为什么__init__被调用两次?

[英]Python logging: Why is __init__ called twice?

我正在尝试将python日志记录与配置文件和自己的处理程序一起使用。 这在某种程度上起作用。 真正困扰我的是__init__被两次调用和__del__被一次调用。 当我删除整个配置文件的内容并直接在代码内创建处理程序时,一次调用__init__ ,而从不调用__del__

我的问题:

  1. 为什么__init__被调用两次?
  2. 为什么__del__调用次数比__init__少?

代码:

#!/bin/env python

import logging
import logging.handlers
import logging.config

class Test1TimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler):
    def __init__(self,filename):
        print "init called"
        logging.handlers.TimedRotatingFileHandler.__init__(self,filename, when='S', interval=86400, backupCount=8, encoding=None)

    def __del__(self):
        print "del called"
        if hasattr(logging.handlers.TimedRotatingFileHandler,"__del__"):
            logging.handlers.TimedRotatingFileHandler.__del__(self)

logging.config.fileConfig('/root/test1.conf')
logger = logging.getLogger("test1")

配置文件:

[formatters]
keys: simple

[handlers]
keys: file

[loggers]
keys: root

[formatter_simple]
format: "%(message)s"

[handler_file]
class: test1.Test1TimedRotatingFileHandler
args: ("/root/test1.log",)
level=INFO

[logger_root]
level: INFO
handlers: file
qualname: test1

输出看起来像这样:

init called
init called
del called

使用Sentinal所建议的调试器来获取堆栈跟踪可以发现以下内容:

首次致电:

> /root/test1.py(12)__init__()
-> print "init called"
(Pdb) where
  /root/test1.py(21)<module>()
-> logging.config.fileConfig('/root/test1.conf')
  /usr/local/python/2.6.4/lib/python2.6/logging/config.py(84)fileConfig()
-> handlers = _install_handlers(cp, formatters)
  /usr/local/python/2.6.4/lib/python2.6/logging/config.py(156)_install_handlers()
-> klass = _resolve(klass)
  /usr/local/python/2.6.4/lib/python2.6/logging/config.py(94)_resolve()
-> found = __import__(used)
  /root/test1.py(21)<module>()
-> logging.config.fileConfig('/root/test1.conf')
  /usr/local/python/2.6.4/lib/python2.6/logging/config.py(84)fileConfig()
-> handlers = _install_handlers(cp, formatters)
  /usr/local/python/2.6.4/lib/python2.6/logging/config.py(159)_install_handlers()
-> h = klass(*args)
> /root/test1.py(12)__init__()
-> print "init called"
(Pdb) c
init called

第二次通话:

> /root/test1.py(12)__init__()
-> print "init called"
(Pdb) w
  /root/test1.py(21)<module>()
-> logging.config.fileConfig('/root/test1.conf')
  /usr/local/python/2.6.4/lib/python2.6/logging/config.py(84)fileConfig()
-> handlers = _install_handlers(cp, formatters)
  /usr/local/python/2.6.4/lib/python2.6/logging/config.py(159)_install_handlers()
-> h = klass(*args)
> /root/test1.py(12)__init__()
-> print "init called"
  1. 为什么init被两次​​调用?

如果遵循logging模块的代码,则会看到在加载日志记录配置文件时,它将实例化所有处理程序(第一次实例化)。

在您的代码中,您声明您的处理程序,如test1.Test1TimedRotatingFileHandler ,因此,当它尝试导入您的处理程序时,它将解析test1模块中的代码……因此,它将重新创建该处理程序!

更正的代码将使用__name__ == '__main__'保护:

#!/bin/env python

import logging
import logging.handlers
import logging.config

class Test1TimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler):
    def __init__(self,filename):
        print "init called"
        logging.handlers.TimedRotatingFileHandler.__init__(self,filename, when='S', interval=86400, backupCount=8, encoding=None)

    def __del__(self):
        print "del called"
        if hasattr(logging.handlers.TimedRotatingFileHandler,"__del__"):
            logging.handlers.TimedRotatingFileHandler.__del__(self)

if __name__ == "__main__":
    logging.config.fileConfig('./test1.conf')
    logger = logging.getLogger("test1")

2。 为什么del调用的次数少于init的调用次数?

通常, __del__运算符称为when-python-wants,更确切地说,是在垃圾回收器决定对对象进行垃圾回收时调用的。 这不一定是在您释放它之后。

您缺少if __name__ == "__main__":保护您的日志记录配置代码。 logging导入您的test1模块以查找类引用时,它将再次执行。

或者,在配置文件中使用名称__main__.Test1TimedRotatingFileHandler ,或者将配置代码和处理程序类放在不同的文件中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM