在Jupyter IPython Notebook中实现丰富的日志输出

5

我正在Jupyter Notebook服务器上运行Python笔记本。 我正在使用Python logging 模块进行记录,目前已连接到像任何控制台应用程序一样的 stdout 进行日志记录,以在Jupyter Notebook输出中显示日志消息。

但是默认的基于 stdout 的日志记录输出感觉受限。 使用HTML输出比纯文本/ANSI输出更具优势。

是否有高级的Jupyter Notebook日志处理程序和格式化程序,可以理解输出为HTML并相应地进行调整? 例如,提供更丰富的格式选项、颜色和字体大小,并交互式地探索日志消息上下文参数,就像Sentry允许我们做的那样?

2个回答

10

以前从未尝试过这样做,但是你可以使用IPython.display.display和自定义的logging.Handler来实现:

import logging
from IPython.display import display, HTML

class DisplayHandler(logging.Handler):
    def emit(self, record):
        message = self.format(record)
        display(message)

这可以用来显示笔记本可以展示的任何内容,包括HTML、Markdown、图片(?)、音频(?)(如果您希望笔记本为您朗读日志)。
我将其与自定义的 logging.Formatter 结合使用,输出一个 HTML 对象以传递给 display()。虽然不太美观,但您可以采用基本概念并改进它,或将两个类组合成单个 NotebookHTMLHandler 类或类似的东西:
class HTMLFormatter(logging.Formatter):
    level_colors = {
        logging.DEBUG: 'lightblue',
        logging.INFO: 'dodgerblue',
        logging.WARNING: 'goldenrod',
        logging.ERROR: 'crimson',
        logging.CRITICAL: 'firebrick'
    }
    
    def __init__(self):
        super().__init__(
            '<span style="font-weight: bold; color: green">{asctime}</span> '
            '[<span style="font-weight: bold; color: {levelcolor}">{levelname}</span>] '
            '{message}',
            style='{'
        )
    
    def format(self, record):
        record.levelcolor = self.level_colors.get(record.levelno, 'black')
        return HTML(super().format(record))

把所有东西放在一起,您可以像这样使用它:

log = logging.getLogger()
handler = DisplayHandler()
handler.setFormatter(HTMLFormatter())
log.addHandler(handler)
log.setLevel(logging.DEBUG)

这是一个示例,看起来是这样的:

enter image description here

对于HTML版本,如果HTML变得足够复杂,您可以通过与类似Jinja的HTML模板引擎组合,进一步简化它,或者添加JavaScript/小部件,使日志消息可扩展以显示更多的日志记录上下文。但我认为完整的解决方案超出了本回答的范围。

太棒了。非常感谢@Iguananaut。我很惊讶IPython没有默认提供这个功能。可能是一个不错的功能可以添加。 - Mikko Ohtamaa
1
@MikkoOhtamaa 谢谢!是的,我真的很喜欢你提出的使用交互式小部件进行丰富日志记录的想法。不过,将其扩展为Jupyter扩展可能是一个好主意,尽管目前我个人没有进一步推进它的强烈需求... - Iguananaut

1
假设您知道要打印的格式化输出类型,您可以使用 IPython.core.display 包。例如,要打印 HTML 格式化输出,您可以执行以下操作:
from IPython.core.display import HTML
HTML('<a href="http://example.com">link</a>')

要打印Markdown格式的输出,你可以这样做:

from IPython.core.display import Markdown
Markdown('# This will be an H1 title')

我不确定你所说的“探索上下文参数”具体是什么意思,也许这里的一个例子可以澄清问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接