Django Broken pipe en modo Debug
broken-pipe (8)
Tengo django 1.3 en el servidor remoto detrás de Nginx.
Si ejecuto django con apache + mod_wsgi, puedo ver los errores en los archivos de registro de Apache. Está bien, pero me gustaría tenerlo en la consola.
Si ejecuto el propio servidor de desarrollo de django, recibo errores con stacktrace en la consola solo cuando DEBUG = False. En salidas de consola del modo 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
Quiero averiguar por qué? ¿Por qué django solo envía Excepción sin nombre? ¿Por qué depende de la variable DEBUG?
Este error se produce principalmente en vistas externas cuando no tengo acceso al objeto de solicitud. Entonces no puedo atraparlo en middleware o usar el manejador de registro.
ACTUALIZAR. Me di cuenta de que si solicito el servidor django directamente, nunca obtengo Broken pipe. Entonces, ¿puede ocurrir el problema mientras Nginx proxy django?
Aquí hay una forma de evitar que se imprima el mensaje en stderr. Simplemente mono parche la función BaseServer.handle_error
. Así es como lo hago:
def patch_broken_pipe_error():
"""Monkey Patch BaseServer.handle_error to not write
a stacktrace to stderr on broken pipe.
https://.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()
Directiva Nginx proxy_intercept_errors off;
(deshabilitado por defecto) es lo que necesitaba
Esto no es realmente un problema con su sitio, más con el servidor dev de Django: vea este boleto de Django . Para decirlo sin rodeos, simplemente ignórelo ya que es un error conocido, y no será corregido.
En los comentarios de ese boleto se da una explicación bastante clara:
Según muchas fuentes, ''Broken Pipe'' es una peculiaridad normal del navegador. Por ejemplo, el navegador lee desde el socket y luego decide que la imagen que ha estado leyendo aparentemente no cambió. El navegador ahora esto (con fuerza) cierra la conexión porque no necesita más datos. El otro extremo de este socket (el servidor de ejecución python) ahora plantea una excepción de socket que le dice al programa que el cliente ''Rompió el socket''.
La directiva nginx (respuesta comprobada) no funcionó para mí, pero la combinación de parches de mono de Igor Katson y Michael_Scharf hizo:
def patch_broken_pipe_error():
"""Monkey Patch BaseServer.handle_error to not write
a stacktrace to stderr on broken pipe.
http://.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()
Lo arreglé. Si usa enlaces, es decir, etiqueta de anclaje, dentro de la página, debe enfrentar el problema de "Tubería de Borken". Solo use dentro de la etiqueta de enlace href = ''#''. No deje el atributo href en blanco. Evitará ese tipo de error.
Me encontré con este problema también durante el uso de tilelite . En realidad, es causado por un error conocido y ahora corregido en Python. Puede resolver este problema aplicando el siguiente parche:
http://bugs.python.org/issue14574
De lo contrario, puede descargar una de las versiones más recientes de python.
Pude deshacerme de esto por
proxy_buffering off;
Esto detiene el almacenamiento en búfer de respuesta del servidor proxy. Esto lleva a otros problemas de la aplicación de back-end que se bloquea por mucho tiempo si el cliente tiene una conexión extremadamente lenta.
Para hacerlo condicional para solicitudes particulares, use X-Accel-Buffering = no en el encabezado de respuesta.
Se me ocurrió un parche de mono rápido y sucio (no sé si elimina cualquier error útil), que elimina este molesto error cuando se usa "./manage.py runserver" o se ejecutan pruebas de LiveServerTestCase.
Simplemente insértalo en cualquier parte de tu código, donde lo necesites:
# 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