使用Python请求模块时尝试/除外

时间:2014-07-01 20:42:41

标签: python python-requests try-except

进行一些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]>

3 个答案:

答案 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,那么你可以认为它是一个错误条件并抛出你自己的异常。