Nginxの背後のリモートサーバーにDjango 1.3があります。
Apache + mod_wsgiでDjangoを実行すると、Apacheログファイルのエラーを見ることができます。大丈夫ですが、コンソールに表示したいと思います。
Django独自の開発サーバーを実行すると、DEBUG = Falseの場合にのみコンソールのスタックトレースでエラーが発生します。DEBUGモードのコンソール出力では
Exception happened during processing of request from (..., ...)
Traceback (most recent call last):
File "/usr/local/python/lib/python2.7/SocketServer.py", line 284, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/local/python/lib/python2.7/SocketServer.py", line 310, in process_request
self.finish_request(request, client_address)
File "/usr/local/python/lib/python2.7/SocketServer.py", line 323, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/local/python/lib/python2.7/site-packages/Django/core/servers/basehttp.py", line 570, in __init__
BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
File "/usr/local/python/lib/python2.7/SocketServer.py", line 641, in __init__
self.finish()
File "/usr/local/python/lib/python2.7/SocketServer.py", line 694, in finish
self.wfile.flush()
File "/usr/local/python/lib/python2.7/socket.py", line 301, in flush
self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
理由を知りたいですか?なぜDjangoは名前のない例外を出力するだけですか?なぜDEBUG変数に依存するのですか?.
このエラーは、リクエストオブジェクトへのアクセス権がない場合、ほとんどの場合ビューの外側で発生します。そのため、ミドルウェアやロギングハンドラーでそれをキャッチすることはできません。
更新。 Djangoサーバーに直接リクエストすると、パイプが壊れることはありません。Nginxプロキシdjangoで問題が発生する可能性があります。
Nginxディレクティブproxy_intercept_errors off;
(デフォルトで無効)は必要なものです
これは実際にはあなたのサイトの問題ではなく、Django devserver:これを参照してください Djangoチケット 。既知のエラーであり、修正されません。
そのチケットのコメントには、非常に明確な説明が記載されています。
多くの情報筋によると、「壊れたパイプ」は通常のブラウザの癖です。たとえば、ブラウザはソケットから読み取り、読み取り中のイメージが明らかに変更されていないと判断します。これでブラウザは、これ以上のデータを必要としないため、(強制的に)接続を閉じます。このソケットのもう一方の端(python runserver)は、クライアントに「ソケットパイプを壊した」ことをプログラムに伝えるソケット例外を発生させます。
Nginxディレクティブ(チェックされた答え)は私には機能しませんでしたが、Igor KatsonとMichael_Scharfのモンキーパッチを組み合わせた場合は機能しました:
def patch_broken_pipe_error():
"""Monkey Patch BaseServer.handle_error to not write
a stacktrace to stderr on broken pipe.
http://stackoverflow.com/a/22618740/362702"""
import sys
from SocketServer import BaseServer
from wsgiref import handlers
handle_error = BaseServer.handle_error
log_exception = handlers.BaseHandler.log_exception
def is_broken_pipe_error():
type, err, tb = sys.exc_info()
return repr(err) == "error(32, 'Broken pipe')"
def my_handle_error(self, request, client_address):
if not is_broken_pipe_error():
handle_error(self, request, client_address)
def my_log_exception(self, exc_info):
if not is_broken_pipe_error():
log_exception(self, exc_info)
BaseServer.handle_error = my_handle_error
handlers.BaseHandler.log_exception = my_log_exception
patch_broken_pipe_error()
メッセージをstderrに出力しないようにする方法を次に示します。ただ monkey patch the BaseServer.handle_error
関数。これは私がそれを行う方法です:
def patch_broken_pipe_error():
"""Monkey Patch BaseServer.handle_error to not write
a stacktrace to stderr on broken pipe.
https://stackoverflow.com/a/7913160"""
import sys
from SocketServer import BaseServer
handle_error = BaseServer.handle_error
def my_handle_error(self, request, client_address):
type, err, tb = sys.exc_info()
# there might be better ways to detect the specific erro
if repr(err) == "error(32, 'Broken pipe')":
# you may ignore it...
logging.getLogger('mylog').warn(err)
else:
handle_error(self, request, client_address)
BaseServer.handle_error = my_handle_error
patch_broken_pipe_error()
私はこれを取り除くことができました
proxy_buffering off;
これにより、プロキシされたサーバーの応答バッファリングが停止します。これにより、クライアントが非常に遅い接続にある場合、バックエンドアプリケーションが長時間ロックされるという別の問題が発生します。
特定の要求に対して条件付きにするには、応答ヘッダーでX-Accel-Buffering = noを使用します。
「./manage.py runserver」を使用したり、LiveServerTestCaseテストを実行したりすると、この厄介なエラーを取り除く、簡単で汚いモンキーパッチ(有用なエラーを抑制するかどうかわかりません)を思い付きました。
必要な場所にコードのどこかに挿入するだけです:
# Monkeypatch python not to print "Broken Pipe" errors to stdout.
import SocketServer
from wsgiref import handlers
SocketServer.BaseServer.handle_error = lambda *args, **kwargs: None
handlers.BaseHandler.log_exception = lambda *args, **kwargs: None
それを私が直した。ページ内でアンカータグなどのリンクを使用する場合、「パイプの破損」問題に直面する必要があります。リンクタグhref = '#'内で使用するだけです。 href属性を空白のままにしないでください。そのタイプのエラーを回避します。
tilelite を使用しているときにもこの問題に遭遇しました。実際には、Pythonの既知のバグと現在修正されたバグが原因です。この問題は、次のパッチを適用することで解決できます。
http://bugs.python.org/issue14574
それ以外の場合は、最新のPythonビルドの1つをダウンロードできます。