You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI中修改sys.excepthook实现traceback单行输出适配云日志平台

FastAPI场景下单行traceback输出方案及sys.excepthook适配说明

sys.excepthook不生效原因

FastAPI基于Uvicorn、Hypercorn等ASGI服务器运行,请求处理全链路的异常会被ASGI服务器、FastAPI内置中间件提前捕获处理,不会触发Python全局sys.excepthook逻辑,因此直接修改该参数无法捕获请求链路内的异常。

是否可以修改sys模块专属参数

可以正常修改包括sys.excepthook在内的sys模块参数,修改操作本身是有效的,只是这类全局钩子不适配FastAPI的ASGI运行模式,仅会作用于主线程非请求链路抛出的未捕获异常(如服务启动阶段的异常),不会在请求处理阶段生效。

FastAPI实现单行traceback的可行方案

  • 方案1:自定义FastAPI全局异常处理器
    直接捕获所有路由层未处理异常,手动格式化traceback为单行输出,示例代码如下:
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import traceback
import logging

app = FastAPI()

@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    # 格式化traceback为单行,替换换行符为自定义分隔符
    tb_single_line = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__)).replace("\n", " | ").strip()
    logging.error(f"path={request.url.path} | err_msg={str(exc)} | traceback={tb_single_line}")
    return JSONResponse(status_code=500, content={"detail": "服务内部错误"})

该方案可以覆盖所有FastAPI路由层抛出的未处理异常。

  • 方案2:自定义logging Formatter全局统一处理
    如需覆盖所有日志场景的异常输出格式,可直接修改logging的异常格式化逻辑,示例代码如下:
import logging

class SingleLineExceptionFormatter(logging.Formatter):
    def formatException(self, exc_info):
        original_tb = super().formatException(exc_info)
        # 替换换行、回车符为指定分隔符
        return original_tb.replace("\n", " | ").replace("\r", "").strip()

# 配置全局日志处理器
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(SingleLineExceptionFormatter("%(asctime)s %(levelname)s %(message)s"))
logging.root.addHandler(stream_handler)
logging.root.setLevel(logging.INFO)

该方案会作用于所有调用logging.exception输出的异常,适用范围更广。

内容的提问来源于stack exchange,提问作者Downey J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 08:48:03