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

如何在Django中全局处理所有异常与回溯?自定义sys.excepthook无效

问题原因

你通过sys.excepthook = ehook设置全局异常钩子未生效,核心原因如下:

  • sys.excepthook仅能处理主线程中未被捕获的顶层异常,但Django的HTTP请求是在独立子线程(或协程)中处理的,这些线程的异常不会触发全局钩子;
  • Django自身存在异常拦截机制,视图层的异常会被框架捕获并转换为HTTP响应(如500页面),不会冒泡到主线程的sys.excepthook;
  • 后台任务、管理命令的子逻辑也可能自带异常捕获逻辑,绕过了全局钩子。

全局异常处理的可行方案

1. 用Django中间件处理Web请求异常

这是捕获用户HTTP请求中异常的核心方式,能覆盖所有视图层、中间件链中的未处理异常。

步骤1:创建自定义中间件

在项目目录下新建middleware/exception_handler.py:

import sys
import traceback
from django.http import HttpResponseServerError
from ehook import ehook

class GlobalExceptionMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        try:
            response = self.get_response(request)
            return response
        except Exception as e:
            # 调用自定义ehook处理异常
            exc_type, exc_value, exc_tb = sys.exc_info()
            ehook(exc_type, exc_value, exc_tb)
            # 返回自定义500响应,也可使用Django默认错误页面
            return HttpResponseServerError("服务器内部错误")

步骤2:注册中间件

在settings.py的MIDDLEWARE列表中添加该中间件(需放在最前面,确保捕获所有后续中间件和视图的异常):

MIDDLEWARE = [
    'your_project.middleware.exception_handler.GlobalExceptionMiddleware',
    # 其他中间件
    'django.middleware.common.CommonMiddleware',
    # ...
]

2. 配置Django日志系统捕获全局异常

Django日志系统可覆盖所有场景(Web请求、命令行、后台任务)的异常,是范围最广的处理方式。

修改settings.py的LOGGING配置,将你的ehook逻辑整合到自定义日志处理器中:

import logging
from logging.handlers import SysLogHandler
from ehook import ehook
import sys

class CustomExceptionLogHandler(logging.Handler):
    def emit(self, record):
        if record.exc_info:
            exc_type, exc_value, exc_tb = record.exc_info
            # 调用自定义ehook处理异常
            ehook(exc_type, exc_value, exc_tb)

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'custom_exception_handler': {
            'class': 'your_project.settings.CustomExceptionLogHandler',
            'level': 'ERROR',
        },
        # 可选:保留syslog输出
        'syslog': {
            'class': 'logging.handlers.SysLogHandler',
            'address': ('your-syslog-server', 514),
            'facility': SysLogHandler.LOG_LOCAL0,
            'level': 'ERROR',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['custom_exception_handler', 'syslog'],
            'level': 'ERROR',
            'propagate': True,
        },
        'django.request': {
            'handlers': ['custom_exception_handler', 'syslog'],
            'level': 'ERROR',
            'propagate': False,
        },
        # 捕获自定义应用的异常
        'your_app': {
            'handlers': ['custom_exception_handler', 'syslog'],
            'level': 'ERROR',
            'propagate': True,
        },
    },
}

3. 处理manage.py命令行异常

如果需要捕获管理命令中的异常,直接修改manage.py,用try-except包裹主逻辑:

import sys
import os
from ehook import ehook

def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tobi.settings')
    try:
        from django.core.management import execute_from_command_line
        execute_from_command_line(sys.argv)
    except Exception as exc:
        exc_type, exc_value, exc_tb = sys.exc_info()
        ehook(exc_type, exc_value, exc_tb)
        # 重新抛出异常,保证命令行正常退出
        raise

if __name__ == '__main__':
    main()

4. 异步任务(如Celery)的异常处理

若使用Celery处理异步任务,需配置任务失败回调:

from celery import Celery
from ehook import ehook
import sys

app = Celery('your_project')

@app.task(bind=True)
def on_task_failure(self, exc, task_id, args, kwargs, einfo):
    exc_type, exc_value, exc_tb = sys.exc_info()
    ehook(exc_type, exc_value, exc_tb)

app.conf.update(
    task_failure_callbacks=[on_task_failure],
)

总结

  • Web请求异常:用中间件处理最直接;
  • 全场景覆盖:用Django日志系统捕获所有未处理异常;
  • 命令行命令:修改manage.py的try-except逻辑;
  • 异步任务:单独配置Celery的任务失败回调。

将你的ehook类整合到上述场景中,即可实现真正的全局异常处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 20:46:12