在调试模式下Django Broken管道

San*_*4ez 48 django broken-pipe

我在Nginx后面的远程服务器上有django 1.3.

如果我用apache + mod_wsgi运行django,我可以在apache日志文件中查看错误.没关系,但我想要在控制台中.

如果我运行django自己的开发服务器,只有在DEBUG = False时才会在控制台中出现stacktrace错误.在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
Run Code Online (Sandbox Code Playgroud)

我想弄明白为什么?为什么django只输出未命名的Exception?为什么它依赖于DEBUG变量.

当我无法访问请求对象时,此错误主要发生在视图外部.所以我无法在中间件或使用日志处理程序中捕获它.

UPDATE.我注意到如果我直接向django服务器请求我永远不会破坏管道.因此,当Nginx代理django时,问题可能会发生吗?

jro*_*jro 55

这对你的网站来说不是一个问题,更多的是使用Django devserver:看看这个Django票.说穿了,只是忽略它,因为它是一个已知的错误,并且不会被修复.

在那张票的评论中给出了一个非常明确的解释:

根据许多消息来源,'Broken Pipe'是一种普通的浏览器怪癖.例如,浏览器从套接字读取,然后决定它正在阅读的图像显然没有改变.浏览器现在(强制)关闭连接,因为它不需要更多数据.此套接字的另一端(python runserver)现在引发一个套接字异常,告诉程序客户端"断开套接字管道".

  • 谢谢.我以前见过那张旧票.我刚刚更新了问题. (2认同)

San*_*4ez 8

Nginx指令proxy_intercept_errors off;(默认情况下禁用)是我需要的


Ric*_*ohr 6

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()
Run Code Online (Sandbox Code Playgroud)