我在Python中构建了一个简短的url翻译引擎,我看到了大量的“断管”错误,我很好奇如何在使用BaseHTTPServer类时最好地捕获它。这并不是全部代码,但让您了解到目前为止我在做什么:
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import memcache
class clientThread(BaseHTTPRequestHandler):
def do_GET(self):
content = None
http_code,response_txt,long_url = \
self.ag_trans_url(self.path,content,'GET')
self.http_output( http_code, response_txt, long_url )
return
def http_output(self,http_code,response_txt,long_url):
self.send_response(http_code)
self.send_header('Content-type','text/plain')
if long_url:
self.send_header('Location', long_url)
self.end_headers()
if response_txt:
self.wfile.write(response_txt)
return
def ag_trans_url(self, orig_short_url, post_action, getpost):
short_url = 'http://foo.co' + orig_short_url
# fetch it from memcache
long_url = mc.get(short_url)
# other magic happens to look it up from db if there was nothing
# in memcache, etc
return (302, None, log_url)
def populate_memcache()
# connect to db, do lots of mc.set() calls
def main():
populate_memcache()
try:
port = 8001
if len(sys.argv) > 1:
port = int(sys.argv[1])
server = HTTPServer(('',port), clientThread)
#server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print '[',str(datetime.datetime.now()),'] short url processing has begun'
server.serve_forever()
except keyboardInterrupt,SystemExit:
print '^C received, shutting down server'
server.socket.close()
代码本身工作得很好,但在生产过程中几乎立即开始抛出错误:
Traceback (most recent call last):
File "/usr/lib/python2.5/SocketServer.py", line 222, in handle_request
self.process_request(request, client_address)
File "/usr/lib/python2.5/SocketServer.py", line 241, in process_request
self.finish_request(request, client_address)
File "/usr/lib/python2.5/SocketServer.py", line 254, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python2.5/SocketServer.py", line 522, in __init__
self.handle()
File "/usr/lib/python2.5/BaseHTTPServer.py", line 316, in handle
self.handle_one_request()
File "/usr/lib/python2.5/BaseHTTPServer.py", line 310, in handle_one_request
method()
File "/opt/short_url_redirector/shorturl.py", line 38, in do_GET
self.http_output( http_code, response_txt, long_url )
File "/opt/short_url_redirector/shorturl.py", line 52, in http_output
self.send_response(http_code)
File "/usr/lib/python2.5/BaseHTTPServer.py", line 370, in send_response
self.send_header('Server', self.version_string())
File "/usr/lib/python2.5/BaseHTTPServer.py", line 376, in send_header
self.wfile.write("%s: %s\r\n" % (keyword, value))
File "/usr/lib/python2.5/socket.py", line 274, in write
self.flush()
File "/usr/lib/python2.5/socket.py", line 261, in flush
self._sock.sendall(buffer)
error: (32, 'Broken pipe')
这些错误的主要原因似乎是调用send_header()方法时出现问题,而我要写的是:
self.send_header('Location', long_url)
所以我很好奇在我的代码中,哪里可以捕获这个IO异常。。。我是否围绕每个self.send_header/self.end_headers/self.wfile.write调用编写try/except调用?我经常看到的另一个错误是这个错误,但不确定要监视哪个异常才能捕获这个错误:
Traceback (most recent call last):
File "/usr/lib/python2.5/SocketServer.py", line 222, in handle_request
self.process_request(request, client_address)
File "/usr/lib/python2.5/SocketServer.py", line 241, in process_request
self.finish_request(request, client_address)
File "/usr/lib/python2.5/SocketServer.py", line 254, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python2.5/SocketServer.py", line 522, in __init__
self.handle()
File "/usr/lib/python2.5/BaseHTTPServer.py", line 316, in handle
self.handle_one_request()
File "/usr/lib/python2.5/BaseHTTPServer.py", line 299, in handle_one_request
self.raw_requestline = self.rfile.readline()
File "/usr/lib/python2.5/socket.py", line 381, in readline
data = self._sock.recv(self._rbufsize)
error: (104, 'Connection reset by peer')
“断管”异常表示代码试图写入另一端已关闭的套接字/管道。如果另一端是web浏览器,则用户可能已停止请求。您可以忽略回溯;它并不表示存在严重问题。如果你想隐藏消息,你可以尝试。。。除了阻塞http_输出函数中的所有代码外,如果愿意,请记录异常。
此外,如果希望HTTP服务器一次处理多个请求,则需要服务器类使用SocketServer.ForkingMixIn和SocketServer.ThreadingMixIn类之一。有关详细信息,请查看SocketServer模块的文档。
Add:“connection reset by peer”异常表示您的代码试图从死套接字读取。如果要禁止回溯,则需要扩展BaseHTTPServer类并重写handle-one-u请求方法以添加try。。。除了布洛克。无论如何,您将需要一个新的服务器类来实现之前关于一次处理多个请求的建议。
这似乎是SocketServer中的一个bug,请参阅此链接Python Bug: 14574
修复方法(在Python2.7中对我有效)是重写SocketServer.StreamRequestHandler finish()方法,如下所示:
在我的应用程序中,错误不是发生在
finish()
中,而是发生在handle()
中。此修复程序捕获broken pipe
错误:相关问题 更多 >
编程相关推荐