【问题标题】:Intercept python stdout and convert to single line拦截python标准输出并转换为单行
【发布时间】:2021-08-27 17:22:02
【问题描述】:

所以,我有一些服务正在运行,控制台中打印的任何内容都被 datadog 代理抓取以显示在 Datadog UI 中。问题是有时当出现意外错误时,堆栈跟踪是多行的,并且在 datadog 中显示为不同的日志。有没有办法自动拦截任何标准输出并将其转换为多行?

我总是可以尝试排除所有内容并在我的记录器中处理它,但尝试排除每段代码可能并不理想?

【问题讨论】:

  • 如果你改变 stderr 来写入某个文件怎么办?
  • 这个拦截应该如何告诉它应该删除哪些“多行” \n 并变成单行,以及哪些作为单行传递?
  • 理想情况下它总是删除多行。当有新消息进来并且每条新消息都应该变成一行时,我希望有一个拦截器
  • stderr 到文件不是一个选项。整个产品基于从标准输出中抓取

标签: python logging stdout


【解决方案1】:

你想要的是改变sys.excepthook

此函数将给定的回溯和异常打印到 sys.stderr。

当异常被引发但未被捕获时,解释器调用 sys.excepthook 并使用三个参数,即异常类、异常实例和回溯对象。在交互式会话中,这发生在控制返回到提示之前;在 Python 程序中,这发生在程序退出之前。可以通过为 sys.excepthook 分配另一个三参数函数来自定义对此类顶级异常的处理。

默认行为是多行打印:

Traceback (most recent call last):
  File "C://PycharmProjects/stackoverflow/67925591.py", line 15, in <module>
    throw()
  File "C://PycharmProjects/stackoverflow/67925591.py", line 10, in throw
    1/0
ZeroDivisionError: division by zero

但是使用这段代码:

import sys
import traceback


def single_line_excepthook(ex_type, ex_value, ex_traceback):
    print(repr(ex_value) + "|".join(traceback.format_tb(ex_traceback)).replace("\n", ""), file=sys.stderr)


def throw():
    1/0


sys.excepthook = single_line_excepthook

throw()

我得到一个单行输出:

ZeroDivisionError('division by zero',)  File "C://PycharmProjects/stackoverflow/67925591.py", line 15, in <module>    throw()|  File "C://PycharmProjects/stackoverflow/67925591.py", line 10, in throw    1/0

【讨论】:

    【解决方案2】:

    @Lenormju comment 完美运行!

    我要补充一点,如果您将记录器配置为输出 json,那么您可能需要将 print 语句更改为 logger.error

    logger = logging.getLogger(__name__)
    def single_line_excepthook(ex_type, ex_value, ex_traceback):
      logger.error(
        "%s\n%s", repr(ex_value), "|".join(traceback.format_tb(ex_traceback))
      )
    

    输出

    {"asctime": "2021-10-16 22:06:02,310", "levelname": "ERROR", "name": "test_file", "filename": "test_file.py", "lineno": 27, "dd.service": null, "dd.env": null, "dd.version": null, "dd.trace_id": null, "dd.span_id": null,
    "message": "ZeroDivisionError('division by zero')\n  File \"<string>\", line 1, in <module>\n|  File \"/code/test_file.py\", line 126, in consume\n    1 / 0\n"}
    

    【讨论】:

      猜你喜欢
      • 2010-10-06
      • 2021-06-24
      • 2011-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-22
      • 2018-05-29
      相关资源
      最近更新 更多