【问题标题】:Correct way to try/except using Python requests module?尝试/除了使用 Python requests 模块的正确方法?
【发布时间】:2013-05-06 20:30:27
【问题描述】:
try:
    r = requests.get(url, params={'s': thing})
except requests.ConnectionError, e:
    print e #should I also sys.exit(1) after this?

这是正确的吗?有没有更好的方法来构建它?这会覆盖我所有的基地吗?

【问题讨论】:

    标签: python request python-requests


    【解决方案1】:

    查看请求exception docs。简而言之:

    如果出现网络问题(例如 DNS 故障、连接被拒绝等),Requests 将引发 ConnectionError 异常。

    如果出现罕见的无效 HTTP 响应,Requests 将引发 HTTPError 异常。

    如果请求超时,则会引发 Timeout 异常。

    如果请求超过配置的最大重定向次数,则会引发 TooManyRedirects 异常。

    Requests 明确引发的所有异常都继承自 requests.exceptions.RequestException

    为了回答您的问题,您展示的内容不会涵盖您的所有基础。您只会捕获与连接相关的错误,而不是超时的错误。

    当您捕获异常时该怎么做取决于您的脚本/程序的设计。可以接受退出吗?你可以继续再试一次吗?如果错误是灾难性的并且您无法继续,那么可以,您可以通过引发 SystemExit 来中止您的程序(打印错误和调用 sys.exit 的好方法)。

    您可以捕获基类异常,它将处理所有情况:

    try:
        r = requests.get(url, params={'s': thing})
    except requests.exceptions.RequestException as e:  # This is the correct syntax
        raise SystemExit(e)
    

    或者你可以分别捕捉它们并做不同的事情。

    try:
        r = requests.get(url, params={'s': thing})
    except requests.exceptions.Timeout:
        # Maybe set up for a retry, or continue in a retry loop
    except requests.exceptions.TooManyRedirects:
        # Tell the user their URL was bad and try a different one
    except requests.exceptions.RequestException as e:
        # catastrophic error. bail.
        raise SystemExit(e)
    

    正如Christian 指出的那样:

    如果您希望 http 错误(例如 401 Unauthorized)引发异常,您可以调用 Response.raise_for_status。如果响应是 http 错误,这将引发 HTTPError

    一个例子:

    try:
        r = requests.get('http://www.google.com/nothere')
        r.raise_for_status()
    except requests.exceptions.HTTPError as err:
        raise SystemExit(err)
    

    将打印:

    404 Client Error: Not Found for url: http://www.google.com/nothere
    

    【讨论】:

    • 处理请求库的细节以及一般异常捕获的非常好的答案。
    • 请注意,由于底层 urllib3 库中存在错误,如果您使用超时,您还需要捕获 socket.timeout 异常:github.com/kennethreitz/requests/issues/1236
    • 未来的评论阅读器:这已在 Requests 2.9(捆绑 urllib3 1.13)中得到修复
    • 如果您希望 http 错误(例如 401 Unauthorized)引发异常,您可以调用 Response.raise_for_status。如果响应是 http 错误,则会引发 HTTPError。
    • Request website 上的例外列表不完整。您可以阅读完整列表here
    【解决方案2】:

    还有一个明确的建议。似乎最好从错误堆栈中的特定到一般,以获取要捕获的所需错误,这样特定错误就不会被一般错误所掩盖。

    url='http://www.google.com/blahblah'
    
    try:
        r = requests.get(url,timeout=3)
        r.raise_for_status()
    except requests.exceptions.HTTPError as errh:
        print ("Http Error:",errh)
    except requests.exceptions.ConnectionError as errc:
        print ("Error Connecting:",errc)
    except requests.exceptions.Timeout as errt:
        print ("Timeout Error:",errt)
    except requests.exceptions.RequestException as err:
        print ("OOps: Something Else",err)
    
    Http Error: 404 Client Error: Not Found for url: http://www.google.com/blahblah
    

    url='http://www.google.com/blahblah'
    
    try:
        r = requests.get(url,timeout=3)
        r.raise_for_status()
    except requests.exceptions.RequestException as err:
        print ("OOps: Something Else",err)
    except requests.exceptions.HTTPError as errh:
        print ("Http Error:",errh)
    except requests.exceptions.ConnectionError as errc:
        print ("Error Connecting:",errc)
    except requests.exceptions.Timeout as errt:
        print ("Timeout Error:",errt)     
    
    OOps: Something Else 404 Client Error: Not Found for url: http://www.google.com/blahblah
    

    【讨论】:

    • 这也是 post 的有效语法吗?
    • @ScipioAfricanus 是的。
    • Max retries exceeded with url: 的例外情况是什么?我已将所有异常添加到异常列表中,但仍未处理。
    【解决方案3】:

    异常对象还包含原始响应e.response,如果需要查看服务器响应的错误正文,这可能很有用。例如:

    try:
        r = requests.post('somerestapi.com/post-here', data={'birthday': '9/9/3999'})
        r.raise_for_status()
    except requests.exceptions.HTTPError as e:
        print (e.response.text)
    

    【讨论】:

      猜你喜欢
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多