我遇到了类似的事情——我们让 Django 支持 NGINX,我们允许 Django 处理 500 次——这在 99.9% 的时间里都有效,但是当我们进行升级时,有时这些“未处理的异常”会漏掉。
Django 不会覆盖 Flup 的处理错误的钩子,所以我们需要自己做,让 Django 处理这些错误。
flup.server.BaseFCGIServer.error
首先通过 Django覆盖错误。然后我们将告诉 Django 使用我们的修改BaseFCGIServer
来查看这些错误。
由于 Python 非常棒,我们将作弊并在一个地方对整个事情进行猴子补丁,django.core.servers.fastcgi.py
. 开始了:
# django.core.servers.fastcgi.py
def runfastcgi(argset=[], **kwargs):
# ...
# Paste his hack right after the `module` try/catch.
# Override BaseFCGIServer.error to use Django error handling.
# http://trac.saddi.com/flup/browser/flup/server/fcgi_base.py#L1210
def patch_error(self, req):
import sys
from django.conf import settings
from django.core import urlresolvers
from django.core.handlers.wsgi import WSGIRequest
urlconf = settings.ROOT_URLCONF
urlresolvers.set_urlconf(urlconf)
resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
# No access to 'environ' so rebuild WSGIRequest.
# http://trac.saddi.com/flup/browser/flup/server/fcgi_base.py#L1077
environ = req.params
environ.update(self.environ)
environ['wsgi.version'] = (1,0)
environ['wsgi.input'] = req.stdin
self._sanitizeEnv(environ)
wsgireq = WSGIRequest(environ)
# http://code.djangoproject.com/browser/django/trunk/django/core/handlers/base.py#L177
response = self.application.handle_uncaught_exception(wsgireq, resolver, sys.exc_info())
# TODO: NGINX figures this out, but other servers might not.
# http://trac.saddi.com/flup/browser/flup/server/fcgi_base.py#L1104
req.stdout.write('Status: 500\r\n')
req.stdout.write('Content-Type: text/html\r\n\r\n' + response.content)
WSGIServer.error = patch_error
现在你可以享受 Django 堆栈跟踪,即使是 Flup 级别的错误!