进行一些API测试并尝试创建一个给定输入URL的函数,它将返回json响应,但是如果HTTP错误是响应,则将返回错误消息。
之前我使用的是urllib2,但现在尝试使用请求。但是,无论错误如何,看起来我的except块都不会被执行。
testURL = 'http://httpbin.org/status/404'
def return_json(URL):
try:
response = requests.get(URL)
json_obj = response.json()
return json_obj
except requests.exceptions.HTTPError as e:
return "Error: " + str(e)
我从上面运行的结果......
<Response [404]>
答案 0 :(得分:22)
如果您希望响应为非200状态代码引发异常,请使用response.raise_for_status()
。您的代码将如下所示:
testURL = 'http://httpbin.org/status/404'
def return_json(URL):
response = requests.get(testURL)
try:
response.raise_for_status()
except requests.exceptions.HTTPError as e:
# Whoops it wasn't a 200
return "Error: " + str(e)
# Must have been a 200 status code
json_obj = response.json()
return json_obj
您可以说这明显比其他解决方案简单,并且不需要您手动检查状态代码。你也可以抓住HTTPError
,因为raise_for_status
会引发这种情况。抓住RequestsException
是一个糟糕的主意。这会抓住像ConnectionError
s或TimeoutError
等等的东西。这些都不是你想要抓住的东西。
答案 1 :(得分:10)
注意:即使这是接受的答案,您也应该按照下面Ian's answer中的说明使用response.raise_for_status()
(他是其中一位维护者) requests
模块)。
如何处理这一切取决于您认为的HTTP错误。有状态代码,但除200
以外的所有内容都不一定意味着存在某种错误。
正如您所注意到的,请求库仅将这些视为HTTP响应的另一个方面,并且不会引发异常。例如,HTTP状态302
表示Found
,但响应不包含响应正文,而是包含Location
标题,而您需要关注以获取您实际需要的资源
因此,您需要查看response.status_code
并对其进行处理,同时使用try..except
捕获实际的协议错误。在捕捉那些时,你应该抓住requests.exceptions.RequestException
,因为这是requests
模块引发的base class for all other exceptions。
所以这是一个演示所有三种情况的例子:
200 OK
回复200
import requests
test_urls = ['http://httpbin.org/user-agent',
'http://httpbin.org/status/404',
'http://httpbin.org/status/500',
'httpx://invalid/url']
def return_json(url):
try:
response = requests.get(url)
# Consider any status other than 2xx an error
if not response.status_code // 100 == 2:
return "Error: Unexpected response {}".format(response)
json_obj = response.json()
return json_obj
except requests.exceptions.RequestException as e:
# A serious problem happened, like an SSLError or InvalidURL
return "Error: {}".format(e)
for url in test_urls:
print "Fetching URL '{}'".format(url)
print return_json(url)
print
输出:
Fetching URL 'http://httpbin.org/user-agent'
{u'user-agent': u'python-requests/2.1.0 CPython/2.7.1 Darwin/11.4.2'}
Fetching URL 'http://httpbin.org/status/404'
Error: Unexpected response <Response [404]>
Fetching URL 'http://httpbin.org/status/500'
Error: Unexpected response <Response [500]>
Fetching URL 'httpx://invalid/url'
Error: No connection adapters were found for 'httpx://invalid/url'
如果你得到一个成功的回复,response.json()
也可能会引发异常,但它根本就不是JSON - 所以你也可能想要考虑到这一点。
注意:if not response.status_code // 100 == 2
位的工作方式如下:
//
运算符执行所谓的floor division,因此它向下舍入到下一个整数(这是Python 2.x中/
的默认行为,但不是Python 3.x ,改变/
进行浮点除法。因此status // 100 == 2
适用于所有2xx
代码。
答案 2 :(得分:1)
您可以查看response.status_code
值。如果它不是200
,那么你可以认为它是一个错误条件并抛出你自己的异常。