在同一个Python的解释器进程里面,所有的对logging.getLogger(‘someLogger’)
的调用都会返回同一个对象.这个规则不仅仅在同一个module有效,而且对在在同一个Python的解释器进程里面的多个module也有效.
而且,应用代码可以在一个module里面定义一个父logger,而在另一个module里面继承这个logger,所有对这个子logger的调用都会转到父logger里面去。
下面例子, 这个是主模块python_log_multimodule1.py
的代码:
#coding=utf-8
import logging
import python_log_multimodule2
from python_log_multimodule2 import SubModule
# create logger with "sp_app" 创建
logger = logging.getLogger("sp_app")
logger.setLevel(logging.DEBUG)
# create file handler which logs even debug messages
fh = logging.FileHandler("spam.log")
fh.setLevel(logging.DEBUG)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
# create formatter and add it to the handlers
formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(thread)d - %(message)s")
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# add the handlers to the logger
logger.addHandler(fh)
logger.addHandler(ch)
logger.info("creating an instance of subModule.SubModule")
a = SubModule()
logger.info("created an instance of subModule.SubModule")
logger.info("calling subModule.SubModule.do_something")
a.do_something()
logger.info("finished subModule.SubModule.do_something")
logger.info("calling subModule.some_function()")
python_log_multimodule2.some_function()
logger.info("done with subModule.some_function()")
这个是子模块的代码,
#coding=utf-8
import time
import logging
# create logger
module_logger = logging.getLogger("sp_app.subModule")
class SubModule:
def __init__(self):
self.logger = logging.getLogger("sp_app.subModule.SubModule")
self.logger.info("creating an instance of subModule")
def do_something(self):
self.logger.info("start doing-something.")
a = 1 + 1
self.logger.info("end doing-something.")
def doWork(self):
self.logger.info("start working.")
time.sleep(0.1)
self.logger.info("end working.")
def some_function():
module_logger.info("received a call to \"some_function\" ")
可以看到, 我们在主模块里面定义了一个logger ‘sp_app’, 并对他进行了配置.那么在这个解释器进程里面的任何地方去通过getLogger(‘sp_app’)得到的对象都是一样的, 不需要从新定义配置, 可以直接使用.
更方便的是, 你定义任意该logger的子logger, 都可以共享父logger的定义和配置.所谓的父子logger只是简单的通过命名来识别, 任意以’sp_app.’开头的logger都是他的子logger, 例如’sp_app.subModule’
这个在实际的开发中, 还是很方便的, 对于一个application,首先通过logging配置文件编写好这个application所对应的log策略, 可以只生成一个根logger, 比如叫’AppName’,然后在Main函数里面, 通过fileConfig加载logging的配置.接着在appliction的任意地方, 不同的模块中, 可以使用AppName的子logger, 如AppName.Util, AppName.Core, 来进行log, 并且不需要反复的定义和配置各个logger.
查看日志记录:
2018-02-27 14:10:49,896 - sp_app - INFO - 140735520973632 - creating an instance of subModule.SubModule
2018-02-27 14:10:49,896 - sp_app.subModule.SubModule - INFO - 140735520973632 - creating an instance of subModule
2018-02-27 14:10:49,897 - sp_app - INFO - 140735520973632 - created an instance of subModule.SubModule
2018-02-27 14:10:49,897 - sp_app - INFO - 140735520973632 - calling subModule.SubModule.do_something
2018-02-27 14:10:49,897 - sp_app.subModule.SubModule - INFO - 140735520973632 - start doing-something.
2018-02-27 14:10:49,897 - sp_app.subModule.SubModule - INFO - 140735520973632 - end doing-something.
2018-02-27 14:10:49,897 - sp_app - INFO - 140735520973632 - finished subModule.SubModule.do_something
2018-02-27 14:10:49,897 - sp_app - INFO - 140735520973632 - calling subModule.some_function()
2018-02-27 14:10:49,897 - sp_app.subModule - INFO - 140735520973632 - received a call to "some_function"
2018-02-27 14:10:49,897 - sp_app - INFO - 140735520973632 - done with subModule.some_function()