【问题标题】:Python: logging comments printed to console before other outputsPython:在其他输出之前记录打印到控制台的注释
【发布时间】:2019-02-16 10:28:20
【问题描述】:

我一直在尝试理解 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() 函数的 sn-p

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

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

【问题讨论】:

  • 在您的addn 函数中,您正在混合print 和日志记录。如果将 print 替换为 self.logger.info 会发生什么?我怀疑打印和记录器的冲洗不会按照您想象的顺序发生。
  • 在这种情况下,理想情况下应该首先打印“加法结果”,因为它在调用 addn 函数之前执行,对吗?...但是在日志消息之后我仍然得到加法结果

标签: python logging


【解决方案1】:

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

为了确保正确排序,首先将所有输出发送到同一管道。例如,您可以将 file=sys.stderr 参数添加到您的打印语句中。

【讨论】:

  • 感谢工作!但我仍然不确定为什么日志打印两次
【解决方案2】:

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

传播:如果此属性评估为真,则记录到此记录器的事件将传递给更高级别(祖先)记录器的处理程序,以及附加到此记录器的任何处理程序。消息直接传递给祖先记录器的处理程序 - 既不考虑所讨论的祖先记录器的级别,也不考虑过滤器。

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

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.

【讨论】:

    【解决方案3】:

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

    stream_handler = logging.StreamHandler(sys.stdout)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-17
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多