Flup での未処理の例外
-
22-08-2019 - |
質問
私は Flup によって引き起こされる恐ろしい「ハンドルされない例外」に直面しています。悲しい部分は、アプリケーション レベル (Django) ではなく、Web サーバー (lighttpd+flup) レベルで発生することです。したがって、問題がどこにあるのかについての 500 メールは送信されません。
私たちのチーム全体は、あいまいなインポートやそのような人がいる場合に備えて、あいまいなインポートによってエラーが発生する可能性を排除するために、コードベースをクリーンアップするのに懸命に苦労しました。そして、コード内の多くの部分をクリーンアップしました。それでも同じ例外です。
正直に言うと、私は Flup のエラー処理に本当にイライラしています。それは何も教えてくれません。さらに悪いことに、同じ「未処理の例外」がユーザーに表示されます。どうすればこれに合格できますか?
lighttpdのログを確認してみました。私が見るのは、「インターフェイスエラー/接続が既に閉じられている」だけです。アプリケートンがFCGIモードで実行されている場合にのみ発生します。したがって、問題は、flupが実際に私のコード(アプリケーション)をどのように処理するかです。どうすればこれに合格できますか?
Flupの代替手段をチェックしましたが、Djangoは明示的にflupに依存しています(これはもう1つの制限であり、私を困惑させました)(参考:django_src/django/core/servers/fastcgi.py line:100 / 131)
このシナリオを (少なくとも) デバッグして問題を解決するにはどうすればよいですか?私を助けてください。アプリケーションは 3 日間ダウンしていました。
解決
私はlighttpdのかFLUPを使用していないので、これは同じくらい、それがヒントであると答えではありません。
あなたはFLUPサーバ.RUN()メソッドを呼び出す前に、私はあなたのアプリケーションのファイルにPDBを実行しようとしている、または少なくともログファイルに書き込むことから始めたいです。そうすれば、あなたは、FastCGIの中やFLUPであるとして、問題を特定することができます。 mod_wsgiをウィキで Pythonのインタラクティブデバッガの項を参照してください。それはあなたのlighttpdとFLUPで同じことを行う方法についてのアイデアを与えるかもしれない。
すると、問題はあなたがPDBで例外をキャッチしますし、そこからデバッグすることができます。FLUPであれば、
問題がlighttpdのであれば、あなたはおそらくあなたの設定ファイルに問題のいくつかの種類、または多分lighttpdのが建設された方法に問題があります。たぶんlighttpとそのFastCGIモジュール間のシステムライブラリの不一致があります?
nginxの+ fastcgiの下にアプリを実行してみて、それが動作するか、少なくともあなたより良いエラーメッセージを与えるかどうかを確認します。
ところで、noreferrer"> rel="nofollow href="http://www.saddi.com/software/news/archives/58-flup-1.0-released.html" のFLUPを使用していない...私はnginxのまたはApache + mod_wsgiのために切り替えをお勧めしたい。
他のヒント
このはよくエラーを示します。このような問題をデバッグするための最速の方法は、FastCGIのデバッグをオンにすることです。これはdjango/core/servers/fastcgi.py
にライン128である。
wsgi_opts['debug'] = False # Turn off flup tracebacks
次に、このような変更はDjangoでアプリケーションを実行して、あなたは全体の栄光でFLUPトレースバックが表示されます。
私も似たようなことを思いつきました。NGINX の背後に Django があり、Django が 500 を処理できるようにしています。これは 99.9% の確率で機能しますが、アップグレードを行っているときに、これらの「未処理の例外」がすり抜けてしまうことがあります。
Django はエラーを処理するために flup のフックをオーバーライドしないため、それを自分で行い、Django にこれらのエラーを処理させる必要があります。
最初のオーバーライド flup.server.BaseFCGIServer.error
Django を介したエラー。次に、変更したものを使用するように Django に指示します。 BaseFCGIServer
それらのエラーを確認します。
Python は素晴らしいので、チートしてすべてを 1 か所にまとめてモンキーパッチします。 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 スタック トレースを楽しめるようになりました。