2016-06-28 40 views
0

我的目标是将日志消息从某个函数重定向到文件中。该功能在另一个模块中定义。我将StreamHandler添加到主记录器,但child_call函数未按预期保存到tmp.log从子模块记录忽略添加的根记录器流处理程序

# main.py 

import logging 
import os 
import sys 
from child_logger import child_call 

logging.basicConfig(format='%(name)s:%(filename)s:%(lineno)d:%(message)s', 
     level=logging.INFO, stream=sys.stdout) 

logger = logging.getLogger(__name__) 
logger.info('here it is') 

with open('tmp.log', 'w') as f: 
    logger_stream_handler = logging.StreamHandler(stream=f) 
    logger_stream_handler.setLevel(logging.INFO) 

    logger.addHandler(logger_stream_handler) 
    logger.info('I am outer') 
    child_call() 
    logger.removeHandler(logger_stream_handler) 


# child_logger.py 

import logging 
logger = logging.getLogger(__name__) 

def child_call(): 
    logger.info('I am inner') 

这里是输出:

%python logger_test.py             
__main__:logger_test.py:18:here it is                                     
__main__:logger_test.py:25:I am outer                                   
child_logger:child_logger.py:9:I am inner 

%cat tmp.log 
I am outer 

我期待看到 '我内' 的tmp.log。就我所了解的日志记录模块而言,创建了一个Logger对象的层次结构,默认情况下,来自子节点的消息应该传播到根Logger,并且根应该处理所有消息。我错过了什么?

回答

1

问题是您的记录器未正确链接。他们需要具有相同的根名称。例如:

# main.py 
logger = logging.getLogger("parent") 

# child_logger.py 
logger = logging.getLogger("parent.child") 

的两个日志检索只要求有一个__name__记录仪,它被设置为模块的名称,除了顶层,它得到“__main__”。您正在使用的这相当于结束了:

# main.py 
logger = logging.getLogger("__main__") 

# child_logger.py 
logger = logging.getLogger("child_logger") 

您需要执行一个共同的父记录名称方案创建正确的记录器继承层次。

+0

谢谢!我认为日志记录会考虑模块层次结构并在内部调整记录器名称以构建相应的层次结构。 – sbond

+0

你有一个想法如何强制* child_logger *使用我想要的处理程序?我无法更改第三方模块child_logger.py,同时我也不想在getLogger调用中显式使用模块名称。也许有一种方法来获得一个包含所有可用Logger的迭代器,然后为它们中的每一个分配一个处理程序? – sbond

+0

@SergiusBond不幸的是我没有。仔细查看记录模块文档,了解可能对您有帮助的功能。如果您没有找到任何内容,请考虑打开一个新问题(搜索重复内容后)。 – skrrgwasme