Python-如何刷新日志? (django)

Posted

技术标签:

【中文标题】Python-如何刷新日志? (django)【英文标题】:Python- How to flush the log? (django) 【发布时间】:2012-10-21 23:41:30 【问题描述】:

我在 Google App Engine 上使用 Django-nonrel,这迫使我使用 logging.debug() 而不是 print()。

“日志”模块由 Django 提供,但我使用它而不是 print() 时遇到了麻烦。

例如,如果我需要验证变量 x 中保存的内容,我将输入logging.debug('x is: %s' % x)。但是如果程序很快就崩溃了(没有刷新流),那么它就永远不会被打印出来。

所以为了调试,我需要在程序出错退出之前刷新 debug(),而这不会发生。

【问题讨论】:

不是你的问题的答案,但你为什么还要使用print?! “刷新”日志到底是什么意思? 希望列举的例子有助于理解。 我会尝试类似AdminEmailHandler 记录处理程序的特定情况,例如您的示例。数据库日志记录处理程序将是更好的选择,不确定是否有免费的Sentry 替代方案。 可能不是正确的,但这对我有用。希望这对某人有所帮助。我尝试使用 flush() 方法,但没有奏效。当我使用 sys.exit(..) 退出我的应用程序时,我在它周围创建了一个包装器方法(exit())...在退出应用程序之前等待1 秒(time.sleep(1))。我还发现任何意外错误并调用exit() 方法。此超时似乎会清除所有待处理的日志消息 【参考方案1】:

如果用例是您有一个在退出时应刷新其日志的 Python 程序,请使用 logging.shutdown()

来自 python 文档:

logging.shutdown()

通知日志系统有序执行 通过刷新和关闭所有处理程序来关闭。这应该称为 在应用程序退出时,不应进一步使用日志系统 在这次通话之后进行的。

【讨论】:

【参考方案2】:

我遇到了类似的问题,这就是我解决它的方法。不要直接使用logging 模块来输出您的日志,而是按如下方式初始化您自己的记录器:

import sys
import logging


def init_logger():
    logger = logging.getLogger()

    h = logging.StreamHandler(sys.stdout)
    h.flush = sys.stdout.flush
    logger.addHandler(h)

    return logger

然后,在您的代码中使用它而不是 logging

def f():
    logger = init_logger()
    logger.debug('...')

因此,您将不再有刷新日志的问题。

【讨论】:

【参考方案3】:

Django 日志记录依赖于标准的 python 日志记录模块。

这个模块有一个模块级别的方法:logging.shutdown(),它会刷新所有的处理程序并关闭日志系统(即调用后日志不能再使用)

检查此函数的代码显示当前(python 2.7)日志记录模块在名为 _handlerList 的模块级变量中保存对所有处理程序的弱引用列表,因此可以通过执行类似操作来刷新所有处理程序

[h_weak_ref().flush() for h_weak_ref in logging._handlerList]

因为这个解决方案使用了模块的内部@Mikes 上面的解决方案更好,但是它依赖于对记录器的访问,它可以概括如下:

 [h.flush() for h in my_logger.handlerList]

【讨论】:

【参考方案4】:

假设您只使用一个(或默认)处理程序,我认为这可能对您有用:

>>> import logging
>>> logger = logging.getLogger()
>>> logging.debug('wat wat')
>>> logger.handlers[0].flush()

不过,这在文档中有点不受欢迎。

应用程序代码不应直接实例化和使用 Handler 的实例。相反,Handler 类是一个基类,它定义了所有处理程序应具有的接口,并建立了一些子类可以使用(或覆盖)的默认行为。 http://docs.python.org/2/howto/logging.html#handler-basic

这可能会消耗性能,但如果你真的卡住了,这可能有助于你的调试。

【讨论】:

呃,如果唯一的方法是通过您不应该访问的处理程序,人们应该如何刷新他们的日志?这听起来很糟糕。 不,这根本不是文档所说的。上面的引用意味着你应该只实例化和使用 Handler 的 子类,而不是直接使用 Handler。您的代码只使用其他人已经实例化的任何处理程序类,所以没有问题。 确实很有帮助;我仍然觉得非常奇怪的是,我无法在其配置中告诉愚蠢的记录器它总是刷新;但是我的客户端代码必须强制执行。 它返回“超出范围”。我使用带有两个处理程序的 .ini 文件初始化了记录器。 logging.hasHandlers() 返回真。 logger.handlers[0].flush() IndexError: list index out of range

以上是关于Python-如何刷新日志? (django)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python Django 中运行单元测试时禁用日志记录?

Django的日志如何配置?

如何使用 Django 1.3 日志字典配置设置 SysLogHandler

在 Python Django 中启用调试时,如何仅关闭 SqlAlchemy 数据库池的日志记录?

Django日志配置

如何在 Django 调试工具栏中使用日志记录?