在调试模式下Django Broken管道

时间:2011-10-27 07:07:34

标签: 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

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

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

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

8 个答案:

答案 0 :(得分:55)

这对您的网站来说不是一个问题,更多的是使用Django devserver:请参阅此Django ticket。直截了当地说,只是忽略它,因为它是一个已知的错误,并且不会被修复。

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

  

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

答案 1 :(得分:8)

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

答案 2 :(得分: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()

答案 3 :(得分:4)

这是一种阻止将消息打印到stderr的方法。只需monkey patch 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()

答案 4 :(得分:2)

我能够通过

摆脱这个
  

proxy_buffering off;

这会停止代理服务器的响应缓冲。如果客户端连接速度极慢,这会导致后端应用程序的其他问题长时间锁定。

要使其成为特定请求的条件,请在响应标头中使用 X-Accel-Buffering = no

答案 5 :(得分:2)

我想出了一个快速而又脏的猴子补丁(我不知道它是否会出现任何有用的错误),当使用“./manage.py runserver”或运行LiveServerTestCase测试时,它会摆脱这个恼人的错误。 / p>

只需将其插入代码中的任何位置即可:

# 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

答案 6 :(得分:0)

我在使用tilelite时遇到了这个问题。它实际上是由python中已知的,现在已修复的错误引起的。您可以通过应用以下修补程序来解决此问题:

http://bugs.python.org/issue14574

否则,你可以下载一个更新的python版本。

答案 7 :(得分:0)

我修好了。 如果您在页面内使用链接,即锚标记,则必须面对" Borken Pipe"问题。只需在链接标记内使用href ='#'。不要将href属性留空。它将避免这种类型的错误。