由于默认处理程序处理重定向(300范围内的代码),并且100-299范围内的代码表示成功,因此通常只能看到400-599范围内的错误代码。
然而以下代码
request = urllib2.Request(url, data, headers)
response = urllib2.urlopen(request)
使用代码201(已创建)引发HTTPError:
ERROR 2011-08-11 20:40:17,318 __init__.py:463] HTTP Error 201: Created
那么为什么urllib2
会在此成功请求中抛出HTTP错误?
这不是太痛苦;我可以轻松地将代码扩展到:
try:
request = urllib2.Request(url, data, headers)
response = urllib2.urlopen(request)
except HTTPError, e:
if e.code == 201:
# success! :)
else:
# fail! :(
else:
# when will this happen...?
但这似乎不是预期的行为,基于文档和我无法找到关于这种奇怪行为的类似问题的事实。
此外,else
块应该期待什么?如果成功的状态代码都被解释为HTTPError
s,那么urllib2.urlopen()
何时返回正常的文件类响应对象,如所有urllib2
文档引用?
答案 0 :(得分:16)
您可以编写自定义Handler
类,以便与urllib2
一起使用,以防止将特定错误代码引发为HTTError
。这是我以前用过的一个:
class BetterHTTPErrorProcessor(urllib2.BaseHandler):
# a substitute/supplement to urllib2.HTTPErrorProcessor
# that doesn't raise exceptions on status codes 201,204,206
def http_error_201(self, request, response, code, msg, hdrs):
return response
def http_error_204(self, request, response, code, msg, hdrs):
return response
def http_error_206(self, request, response, code, msg, hdrs):
return response
然后你就可以使用它:
opener = urllib2.build_opener(self.BetterHTTPErrorProcessor)
urllib2.install_opener(opener)
req = urllib2.Request(url, data, headers)
urllib2.urlopen(req)
答案 1 :(得分:3)
正如实际的图书馆文档所述:
对于200个错误代码,立即返回响应对象。
对于非200错误代码,这只是通过OpenerDirector.error()将作业传递给protocol_error_code处理程序方法。最终,如果没有其他处理程序处理错误,urllib2.HTTPDefaultErrorHandler将引发HTTPError。
http://docs.python.org/library/urllib2.html#httperrorprocessor-objects
答案 2 :(得分:0)
我个人认为这是默认行为,这是一个错误并且非常不直观。 确实,非2XX代码暗含协议级别错误,但将其转换为异常实在是太遥远了(至少在我看来)。
无论如何,我认为避免这种情况的最优雅的方法是:
opener = urllib.request.build_opener()
for processor in opener.process_response['https']: # or http, depending on what you're using
if isinstance(processor, urllib.request.HTTPErrorProcessor): # HTTPErrorProcessor also for https
opener.process_response['https'].remove(processor)
break # there's only one such handler by default
response = opener.open('https://www.google.com')
现在您有了响应对象。您可以检查其状态码,标题,正文等。