尝试/使用Python请求模块的正确方法?


Answers:


794

看一下Requests 异常文档。简而言之:

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

如果发生罕见的无效HTTP响应,则请求将引发HTTPError异常。

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

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

请求显式引发的所有异常都继承自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)

正如克里斯蒂安指出:

如果您希望http错误(例如401未经授权)引发异常,可以致电Response.raise_for_statusHTTPError如果响应是http错误,则将引发。

一个例子:

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

11
处理请求库的细节以及一般异常捕获的很好答案。
Brian Peterson 2014年

10
请注意,由于底层urllib3库中的错误,socket.timeout如果您使用超时,还需要捕获异常:github.com/kennethreitz/requests/issues/1236
jb。

15
未来的评论读者:已在请求2.9(与urllib3 1.13捆绑在一起)中修复了此问题
RazerM,2016年

14
如果您希望http错误(例如401未经授权)引发异常,则可以调用Response.raise_for_status。如果响应是http错误,则将引发HTTPError。
克里斯蒂安·朗

5
请求网站上的例外列表不完整。您可以在此处阅读完整列表。
Epoc

87

另一项建议是明确的。似乎最好是从特定错误到一般错误,以获取所需的错误来捕获,因此特定错误不会被一般错误掩盖。

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

@ScipioAfricanus是的。
andrea

10

异常对象还包含原始响应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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.