【问题标题】:werkzeug: disable bash colors when logging to filewerkzeug:记录到文件时禁用 bash 颜色
【发布时间】:2021-01-22 03:49:43
【问题描述】:

在 Flask 应用程序中,我使用 RotatingFileLogger 将 werkzeug 访问日志记录到文件中,如 this question 所示:

file_handler_access_log = RotatingFileHandler("access.log",
                                              backupCount=5,
                                              encoding='utf-8')
formatter = logging.Formatter('%(asctime)s %(module)s %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
file_handler_access_log.setFormatter(formatter)
werkzeug_logger.addHandler(file_handler_access_log)
werkzeug_logger.setLevel(logging.DEBUG)

access.log 文件中,请求如下所示:

2020-10-07 09:43:51 _internal INFO: 127.0.0.1 - - [07/Oct/2020 09:43:51] "[37mGET /api/foo HTTP/1.1[0m" 200 -

我想去掉日志文件中 [37m 这样的颜色代码。

werkzeug documentation 声明:

开发服务器可以选择突出显示请求登录 基于状态码的不同颜色。安装 点击启用 这个功能。

Click 是一个 Flask 依赖项,所以我无法卸载它。如何禁用彩色日志记录?

【问题讨论】:

  • 你能分享一下formatter的定义吗?
  • @DušanMaďar 我在代码中添加了它。颜色代码出现在%(message)s 部分。

标签: python python-3.x flask logging werkzeug


【解决方案1】:

这与@jhodges 的想法相似,但更简单 - 它只是完全删除了所有“点击”模块的样式。

import click
click.style = lambda text, *args, **kwargs: text

编辑:最后,我最终使用了一个过滤器来从发送给文件处理程序的日志消息中删除转义序列。因为 werkzeug 将转义序列放在日志消息的 args 列表中,所以也需要删除这些转义序列。这是基本大纲:

class NoEscape(logging.Filter):
    def __init__(self):
        self.regex = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]')
    def strip_esc(self, s):
        try: # string-like 
            return self.regex.sub('',s)
        except: # non-string-like
            return s
    def filter(self, record: logging.LogRecord) -> int:
        record.msg = self.strip_esc(record.msg)
        if type(record.args) is tuple:
            record.args = tuple(map(self.strip_esc, record.args))
        return 1

希望这会有所帮助!

【讨论】:

  • 实际上我不想删除所有 click 的样式,因为我也登录到控制台,我想将彩色输出保留在那里,并且只从记录到文件的记录器中删除颜色代码。
  • 很抱歉恢复一个月前的线程,但最后我会和你一样,只需要实现一个过滤器来去除逃逸。如果您仍在使用此功能,请参见上文。希望这会有所帮助!
【解决方案2】:

我选择了一个我认为更直接的解决方案,即简单地丢弃所有样式参数 - 在你的应用程序启动中像这样


    old_color = click.style

    def new_color(text, fg=None, bg=None, bold=None, dim=None, underline=None, blink=None, reverse=None, reset=True):
        return old_color(text)

    # replace flask styling with non-colorized styling
    click.style = new_color

【讨论】:

    【解决方案3】:

    好的,所以你要打的是

    if click:
        color = click.style
    
        if code[0] == "1":  # 1xx - Informational
            msg = color(msg, bold=True)
        ...
    self.log("info", '"%s" %s %s', msg, code, size)
    

    来源:https://github.com/pallets/werkzeug/blob/ef545f0d0bf28cbad02066b4cb7471bea50a93ee/src/werkzeug/serving.py

    不容易阻止这种行为。第二个选项是从消息中删除颜色代码。我会尝试使用log Filter 来更新消息,例如

    import logging
    
    import click
        
    
    class RemoveColorFilter(logging.Filter):
        def filter(self, record):
            if record and record.msg and isinstance(record.msg, str):
                record.msg = click.unstyle(record.msg) 
            return True
    
    remove_color_filter = RemoveColorFilter()
    file_handler_access_log.addFilter(remove_color_filter)
    

    上述建议的灵感来自以下答案https://stackoverflow.com/a/60692906/4183498

    我没有测试建议的解决方案。

    【讨论】:

    • 其他一些库会记录错误对象而不是字符串,因此会导致类型错误。我在您的答案中添加了类型检查
    • 除了类型检查之外,您还可以使用if record and record.name == 'werkzeug'排除其他记录器
    猜你喜欢
    • 2016-05-23
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多