59

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

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

如果我运行 django 自己的开发服务器,只有当 DEBUG = False 时,我才会在控制台中收到堆栈跟踪错误。在 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 只输出未命名的异常?为什么它取决于 DEBUG 变量。

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

更新。我注意到如果我直接向 django 服务器请求,我永远不会得到 Broken pipe。那么Nginx代理django时可能会出现问题吗?

4

10 回答 10

66

这不是您的站点的真正问题,更多的是 Django 开发服务器:请参阅此Django 票证。说白了就是忽略它,因为它是一个已知的错误,并且不会被修复。

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

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

于 2011-10-27T08:03:35.753 回答
12

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

于 2011-10-28T08:45:35.200 回答
7

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()
于 2014-03-24T19:24:43.977 回答
4

这是一种防止将消息打印到 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()
于 2014-02-14T19:52:33.260 回答
3

我能够摆脱这个

proxy_buffering 关闭;

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

要使其对特定请求有条件,请在响应标头中使用X-Accel-Buffering=no 。

于 2013-03-16T06:44:06.567 回答
3

我想出了一个快速而肮脏的猴子补丁(我不知道它是否会抑制任何有用的错误),它可以在使用“./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
于 2013-03-26T23:43:58.750 回答
1

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

于 2013-09-11T07:07:27.690 回答
0

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

http://bugs.python.org/issue14574

否则,您可以下载最新版本的 python 之一。

于 2013-03-25T20:46:32.743 回答
0

在 Django 3.2+ 中,“错误”INFO报告logging类似于:

INFO - Broken pipe from ('127.0.0.1', 59895)

@igor-katson 有一个快速而肮脏的猴子补丁。更新为 3.2+ 它可以是:

# Suppress broken pipe errors
from django.core.servers.basehttp import WSGIServer
WSGIServer.handle_error = lambda *args, **kwargs: None

If you have a conditional check for being in development (runserver) mode in your settings.py, you could put this code there. It will squelch that annoying log entry.

Keep in mind, WSGIServer.handle_error also reports non-socket errors. If you had some other connectivity issue to debug this may get in the way.

于 2021-10-08T00:03:49.217 回答
0

My BrokenPipe error disappears when I remove the "/" in the path in "urls.py"

urlpatterns = [
    path('', views.index)
]
于 2021-10-12T09:08:18.703 回答