3

我有一个相当简单、天真的 Python/WSGI/Pyramid 网络服务器。

它在使用wsgiref.simple_server.make_server(), 构建的服务器上运行pyramid.config.Configurator().make_wsgi_app()。这台服务器工作正常。

但是,它所服务的应用程序有很多javascript 图像鼠标悬停弹出窗口。如果您在页面上运行鼠标,它可以生成 20 多个图像请求。这也很好(这是内部的事情,不是很多用户)。

但是,这样做会导致服务器发出类似六个错误回溯的信息:

10.1.1.4 - - [25/Apr/2014 01:56:42] "GET /*SNIP* 500 59
----------------------------------------
Exception happened during processing of request from ('10.1.1.4', 18338)
Traceback (most recent call last):
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 180, in finish_response
    self.write(data)
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 274, in write
    self.send_headers()
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 333, in send_headers
    self._write(bytes(self.headers))
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 453, in _write
    self.stdout.write(data)
  File "/usr/lib/python3.4/socket.py", line 391, in write
    return self._sock.send(b)
BrokenPipeError: [Errno 32] Broken pipe

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 141, in run
    self.handle_error()
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 368, in handle_error
    self.finish_response()
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 180, in finish_response
    self.write(data)
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 274, in write
    self.send_headers()
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 331, in send_headers
    if not self.origin_server or self.client_is_modern():
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 344, in client_is_modern
    return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9'
TypeError: 'NoneType' object is not subscriptable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.4/socketserver.py", line 306, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python3.4/socketserver.py", line 332, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python3.4/socketserver.py", line 345, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python3.4/socketserver.py", line 666, in __init__
    self.handle()
  File "/usr/lib/python3.4/wsgiref/simple_server.py", line 126, in handle
    handler.run(self.server.get_app())
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 144, in run
    self.close()
  File "/usr/lib/python3.4/wsgiref/simple_server.py", line 35, in close
    self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'

我明白为什么我会遇到管道错误(图像请求在图像完全传输之前被取消,因为鼠标悬停弹出窗口已关闭),它似乎无害。

但是,我不知道如何使这种回溯保持沉默。我的日志中有数千个,这使得调试实际错误成为一场噩梦。我不在乎我遇到了管道错误,我怎样才能抓住它们并默默地吞下它们?

似乎wsgiref.simple_server.make_server()安装了一个内部处理程序来捕获BrokenPipeError: [Errno 32] Broken pipe,打印回溯,然后吞下错误。我尝试将run_server()调用包装在 try-except 子句中,但它没有任何效果。

4

2 回答 2

0

我最后只是切换到使用CherryPy WSGI Server。它不会受到损坏的管道日志问题的影响,并且可能也更加健壮。

它还使用线程池,因此它的性能也更高(多个请求不会阻塞!)。

于 2014-04-26T06:30:58.363 回答
0

我没有找到实现此目的的直接方法,但是,您总是可以做一些猴子补丁:

from wsgiref.handlers import BaseHandler
import sys


def ignore_broken_pipes(self): 
    if sys.exc_info()[0] != BrokenPipeError: BaseHandler.__handle_error_original_(self)

BaseHandler.__handle_error_original_ = BaseHandler.handle_error
BaseHandler.handle_error = ignore_broken_pipes

在开始的某个地方运行此代码后,您将不会再看到这些烦恼。

wsgiref对我来说,它看起来像是实现中的某个错误BaseHandler

def handle_error(self):
    """Log current error, and send error output to client if possible"""
    self.log_exception(sys.exc_info())
    if not self.headers_sent:
        self.result = self.error_output(self.environ, self.start_response)
        self.finish_response()
    # XXX else: attempt advanced recovery techniques for HTML or text?

如果BrokenPipeError通过此方法处理,则finish_response崩溃。如果管道坏了,为什么我们要完成响应?数据发送到哪里?

于 2016-02-23T19:20:23.070 回答