Django Разбитая труба в режиме отладки - PullRequest
48 голосов
/ 27 октября 2011

У меня есть django 1.3 на удаленном сервере за Nginx.

Если я запускаю django с apache + mod_wsgi, я могу наблюдать ошибки в файлах журнала apache.Это нормально, но я хотел бы иметь в консоли.

Если я запускаю собственный сервер разработки django, я получаю ошибки с помощью stacktrace в консоли, только когда DEBUG = False.В режиме отладки консольные выходы

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?

Ответы [ 8 ]

55 голосов
/ 27 октября 2011

Это на самом деле не проблема с вашим сайтом, а с сервером разработки Django: см. билет Django .Проще говоря, просто проигнорируйте это, поскольку это известная ошибка, и она не будет исправлена.

В комментариях к этому билету дано довольно четкое объяснение:

СогласноВо многих источниках «Сломанная труба» - это обычная причуда браузера.Например, браузер читает из сокета и затем решает, что изображение, которое он читал, по-видимому, не изменилось.Браузер теперь (принудительно) закрывает соединение, потому что ему не нужно больше данных.Другой конец этого сокета (сервер выполнения python) теперь вызывает исключение сокета, сообщающее программе, что клиент «сломал канал сокета».

8 голосов
/ 28 октября 2011

Директива Nginx proxy_intercept_errors off; (по умолчанию отключена) - это то, что мне нужно

6 голосов
/ 24 марта 2014

Директива 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()
4 голосов
/ 14 февраля 2014

Вот способ предотвратить печать сообщения на 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()
2 голосов
/ 27 марта 2013

Я разработал быстрый и грязный патч для обезьян (я не знаю, подавляет ли он какие-либо полезные ошибки), который избавляет от этой надоедливой ошибки при использовании «./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
2 голосов
/ 16 марта 2013

Я смог избавиться от этого с помощью

proxy_buffering off;

Останавливает буферизацию ответа прокси-сервера. Это приводит к тому, что другие проблемы с внутренним приложением блокируются на длительное время, если клиент находится на очень медленном соединении.

Чтобы сделать его условным для определенных запросов, используйте X-Accel-Buffering = no в заголовке ответа.

0 голосов
/ 11 сентября 2013

Я исправил это. Если вы используете ссылки, т. Е. Якорный тег, внутри страницы, вам придется столкнуться с проблемой «Труба Боркена». Просто используйте внутри тега ссылки href = '#'. Не оставляйте атрибут href пустым. Это позволит избежать ошибок такого типа.

0 голосов
/ 26 марта 2013

Я тоже сталкивался с этой проблемой при использовании tilelite .Это на самом деле вызвано известной и теперь исправленной ошибкой в ​​python.Вы можете решить эту проблему, применив следующий патч:

http://bugs.python.org/issue14574

В противном случае вы можете загрузить одну из последних сборок Python.

...