Ответ 1
Директива Nginx proxy_intercept_errors off;
(по умолчанию отключена) - это то, что мне нужно
У меня есть django 1.3 на удаленном сервере за Nginx.
Если я запускаю django с apache + mod_wsgi, я могу наблюдать ошибки в файлах журнала apache. Это нормально, но я хотел бы иметь консоль.
Если я запускаю собственный сервер разработки django, я получаю ошибки с помощью stacktrace в консоли только тогда, когда 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.
Эти ошибки возникают в основном из внешних представлений, когда у меня нет доступа к объекту запроса. Поэтому я не могу поймать его в промежуточном программном обеспечении или с помощью обработчика ведения журнала.
UPDATE. Я заметил, что если я запрошу сервер django напрямую, я никогда не получаю Broken pipe. Так может возникнуть проблема, когда Nginx proxy django?
Директива Nginx proxy_intercept_errors off;
(по умолчанию отключена) - это то, что мне нужно
Это не проблема с вашим сайтом, больше с Django devserver: см. этот Django ticket. Чтобы сказать это прямо, просто игнорируйте его, поскольку это известная ошибка, и не будет исправлена.
В комментариях к билету дается достаточно четкое объяснение:
Согласно многим источникам, "Broken Pipe" - обычная причуда браузера. Например, браузер читает из сокета, а затем решает, что изображение, которое оно читает, по-видимому, не изменилось. Браузер теперь (принудительно) закрывает соединение, потому что ему не нужно больше данных. Другой конец этого сокета (python runningerver) теперь вызывает исключение сокета, указывающее программе, что клиент "сломал трубку сокета".
Директива nginx (проверенный ответ) не сработала для меня, но комбинация патчей обезьян от Игоря Катсона и Майкла_Шарфа сделала:
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. Просто патч обезьяны
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 runningerver" или запускает тесты 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
Я столкнулся с этой проблемой, используя tilelite. Это фактически вызвано известной, а теперь исправленной ошибкой в python. Вы можете решить эту проблему, применив следующий патч:
http://bugs.python.org/issue14574
В противном случае вы можете загрузить одну из последних версий python.
Я исправил его. Если вы используете ссылки, т.е. Тег привязки, внутри страницы, вам придется столкнуться с проблемой "Borken Pipe". Просто используйте внутри тега ссылки href= '#'. Не оставляйте атрибут href пустым. Это позволит избежать такого типа ошибок.