我有一个相当简单,天真的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子句中,但它没有任何效果。
答案 0 :(得分:0)
我最后转而使用CherryPy WSGI Server。它没有遭受破坏的管道日志问题,也可能更加健壮。
它也使用了线程池,所以它也更高效(多个请求没有阻塞!)。
答案 1 :(得分: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
的{{1}}实施中,它看起来像是一个错误:
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
崩溃。如果管道坏了,我们为什么要完成响应?数据发送到哪里?