Python日志记录:为什么__init__被调用两次? [英] Python logging: Why is __init__ called twice?

查看:557
本文介绍了Python日志记录:为什么__init__被调用两次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to use python logging with a config file and an own handler. This works to some degree. What really puzzle me is __init__ being called twice and __del__ being called once. When I remove the whole config file stuff and create the handler directly within the code __init__ is called once and __del__ is never called.

我的问题:

  1. 为什么__init__被两次调用?
  2. 为什么__del__的调用频率少于__init__?
  1. Why is __init__ called twice?
  2. Why is __del__ called less often than __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的建议,使用调试器获取堆栈跟踪可以揭示这一点:

Using the debugger to get the stack trace as suggested by Sentinal reveals this:

首次通话:

> /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模块的代码,则会看到在加载日志记录配置文件时,它将实例化所有处理程序(第一"实例化).

If you follow the code of the logging module, you'll see that when you're loading the logging configuration file, it instantiates all the handlers (First instantiation).

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

In your code, you declare your handler like test1.Test1TimedRotatingFileHandler, so when it try to import your handler, it parses the code in the test1 module... so it recreates the handler !!

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

Corrected code will guard using __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的次数少?

2 . Why is del called less often than init?

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

In general, the __del__ operator is called when-python-wants, more exactly, it is called when the garbage collector decides to garbage-collect the object; this is not necessarily just after you release it.

这篇关于Python日志记录:为什么__init__被调用两次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆