Python日志记录:为什么__init__被调用两次? [英] Python logging: Why is __init__ called twice?
问题描述
我正在尝试将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.
我的问题:
- 为什么
__init__
被两次调用? - 为什么
__del__
的调用频率少于__init__
?
- Why is
__init__
called twice? - 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"
推荐答案
- 为什么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屋!