J'ai Django 1.3 sur le serveur distant derrière Nginx.
Si je lance Django avec Apache + mod_wsgi, je peux détecter les erreurs dans les fichiers journaux Apache. C'est bon mais j'aimerais avoir en console.
Si j'exécute le propre serveur de développement de Django, les erreurs avec stacktrace dans la console ne sont générées que lorsque DEBUG = False. En mode DEBUG, sorties de la console
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
Je veux comprendre pourquoi? Pourquoi Django produit-il simplement une exception sans nom? Pourquoi cela dépend-il de la variable DEBUG?.
Cette erreur se produit principalement en dehors des vues lorsque je n'ai pas accès à l'objet de requête. Donc, je ne peux pas l'attraper dans le middleware ou en utilisant le gestionnaire de journalisation.
METTRE À JOUR. J'ai remarqué que si je demande directement au serveur Django, je ne reçois jamais de tuyau cassé. Donc, le problème peut-il se produire lorsque Nginx proxy django?
La directive Nginx proxy_intercept_errors off;
(désactivée par défaut) est ce dont j'avais besoin
Ce n'est pas vraiment un problème avec votre site, mais plutôt avec le devserver de Django: voir ce billet Django . Pour le dire franchement, ignorez-le, car il s'agit d'une erreur connue et ne sera pas corrigé.
Dans les commentaires de ce ticket, une explication assez claire est donnée:
Selon de nombreuses sources, le "tuyau cassé" est une bizarrerie normale pour les navigateurs. Par exemple, le navigateur lit à partir du socket, puis décide que l'image qu'il a lue n'a apparemment pas changé. Le navigateur maintenant cela (force) ferme la connexion car il n'a pas besoin de plus de données. L'autre extrémité de ce socket (le serveur d'exécution python) déclenche maintenant une exception de socket indiquant au programme que le client 'a cassé le tube de socket'.
La directive nginx (réponse cochée) n'a pas fonctionné pour moi, mais la combinaison des patchs de singe d'Igor Katson et de Michael_Scharf a eu les effets suivants:
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()
Voici un moyen d’empêcher l’impression du message sur stderr. Juste singe patch la fonction BaseServer.handle_error
. Voici comment je le fais:
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()
J'ai pu m'en débarrasser en
proxy_buffering off;
Cela arrête la mise en mémoire tampon des réponses du serveur mandaté. Cela entraîne d'autres problèmes de verrouillage de l'application dorsale pendant longtemps si le client utilise une connexion extrêmement lente.
Pour le rendre conditionnel pour des requêtes particulières, utilisez X-Accel-Buffering = no dans l'en-tête de la réponse.
Je suis arrivé avec un patch singe rapide et sale (je ne sais pas s'il supprime les erreurs utiles), qui supprime cette erreur gênante lorsque vous utilisez "./manage.py runserver" ou exécutez des tests LiveServerTestCase.
Il suffit de l'insérer n'importe où dans votre code, là où vous en avez besoin:
# 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
Je l'ai corrigé . Si vous utilisez des liens i.e, balise d'ancrage, dans la page, vous devez faire face au problème "Borken Pipe". Utilisez simplement la balise de lien href = '#'. Ne laissez pas l'attribut href vide. Cela évitera ce type d'erreur.
Je suis également tombé sur ce problème en utilisant tilelite . C'est en fait causé par un bogue connu et maintenant corrigé en python. Vous pouvez résoudre ce problème en appliquant le correctif suivant:
http://bugs.python.org/issue14574
Sinon, vous pouvez télécharger l'une des versions les plus récentes de Python.