Python:在其他输出之前记录打印到控制台的注释

时间:2019-02-16 10:28:20

标签: python logging

我一直在尝试了解python中的日志记录。我有一个 init 模块,另外两个模块和一个主模块。由于某些原因,当我运行模块时,日志详细信息会跳过代码流,并在其他输出之前首先打印

有人可以告诉我为什么会这样吗

这是在__init__.py

from dir1.mod1 import FirstClass
from dir1.mod2 import SecondClass

logger = logging.getLogger(__name__)

logger.setLevel(logging.DEBUG)
f_handler=logging.FileHandler('python_logs.log')
f_handler.setLevel(logging.DEBUG)
c_handler = logging.StreamHandler()
c_handler.setLevel(logging.ERROR)

f_formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
c_formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')

f_handler.setFormatter(f_formatter)
c_handler.setFormatter(c_formatter)

logger.addHandler(f_handler)
logger.addHandler(c_handler)

这是在其他两个模块中(写在resp类的__init__()

self.logger = logging.getLogger(__name__)

在模块之一内部定义的addn()函数的代码段

def addn(self):
    z=self.x +self.y
    print('sum is '+z)
    self.logger.error('incrementing number!')
    self.logger.info('Still incrementing number!!')
    return z

我运行的主要模块具有以下功能:

from dir1.mod1 import FirstClass
from dir1.mod2 import SecondClass

number = FirstClass(2,2)
print('addition results')
number.addn()

我期望输出如下

添加结果

总和为3

dir1.mod1-错误-递增数字!

但是我得到的是

dir1.mod1-错误-递增数字!

dir1.mod1-错误-递增数字!

附加结果:

总和为3

为什么首先打印的日志消息跳出代码流?还有谁能告诉我为什么日志消息要打印两次?

3 个答案:

答案 0 :(得分:4)

U可以尝试禁用记录器的传播属性。

  

传播:如果此属性的值为true,则除了附加到此记录器的任何处理程序外,记录到该记录器的事件还将传递到更高级别(祖先)记录器的处理程序中。邮件直接传递给祖先记录器的处理程序-既不考虑所讨论祖先记录器的级别也没有过滤器。

这是一个初始化记录器的示例,该记录器使用具有不同调试级别的文件和标准输出:

def init_logger_singleton():

    global logger

    logger = logging.getLogger(name='loggerName')
    logger.propagate = False
    logger.setLevel(10)
    formatter = logging.Formatter(
        '\t%(message)s'
    )

    filehandler = logging.StreamHandler()
    filehandler.setLevel(40)
    filehandler.setFormatter(formatter)
    logger.addHandler(filehandler)

我使用数字来定义日志级别,但是10 = DEBUG和40 = ERRO。有关更多信息,请访问this link.

答案 1 :(得分:3)

默认情况下,当您将打印语句发送到stdout时,Python StreamHandler将默认登录到stderr。这是两个不同的管道,不能保证它们之间的顺序。

通过将所有输出发送到同一管道来确保正确订购。例如,您可以在打印语句中添加file=sys.stderr参数。

答案 2 :(得分:0)

您还可以将参数 sys.stdout 添加到您的流处理程序,因此 print 和记录器事件都将传递到一个通道。

stream_handler = logging.StreamHandler(sys.stdout)