使用 Python 请求模块时尝试/除外
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24518944/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Try/except when using Python requests module
提问by mroriel
Doing some API testing and trying to create a function that given an inputted URL it will return the json response, however if a HTTP error is the response an error message will be returned.
进行一些 API 测试并尝试创建一个函数,该函数给出输入的 URL,它将返回 json 响应,但是如果响应是 HTTP 错误,则将返回错误消息。
I was using urllib2 before, but now trying to use requests instead. However it looks like my except block is never executed, regardless of the error.
我之前使用 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)
The result I get from running the above...
我从上面运行得到的结果......
<Response [404]>
采纳答案by Ian Stapleton Cordasco
If you want the response to raise an exception for a non-200 status code use response.raise_for_status()
. Your code would then look like:
如果您希望响应引发非 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
You can tell that this is clearly simpler than the other solutions here and doesn't require you to check the status code manually. You would also just catch an HTTPError
since that is what raise_for_status
will raise. Catching RequestsException
is a poor idea. That will catch things like ConnectionError
s or TimeoutError
s, etc. None of those mean the same thing as what you're trying to catch.
您可以看出这显然比此处的其他解决方案更简单,并且不需要您手动检查状态代码。你也会抓住一个,HTTPError
因为那是raise_for_status
会引起的。捕捉RequestsException
是一个坏主意。这将捕获诸如ConnectionError
s 或TimeoutError
s 之类的东西。这些都与您要捕获的含义不同。
回答by austin
You can check the response.status_code
value. If it's not 200
, then you can consider it to be an error condition and throw your own exception.
您可以检查该response.status_code
值。如果不是200
,那么您可以将其视为错误条件并抛出您自己的异常。
回答by Lukas Graf
Note: You should rather go with response.raise_for_status()
as described in Ian's answerabove (he's one of the maintainers of the requests
module).
注意:您应该response.raise_for_status()
按照上面Ian 的回答中的描述进行操作(他是该requests
模块的维护者之一)。
How you handle this all depends on what you consider an HTTP error. There's status codes, but not everything other than 200
necessarily means there's an error of some sort.
您如何处理这一切取决于您认为 HTTP 错误是什么。有状态代码,但并非所有其他内容都200
意味着存在某种错误。
As you noticed, the request library considers those just another aspect of a HTTP response and doesn't raise an exception. HTTP status 302
for example means Found
, but the response doesn't contain a response body but a Location
header instead that you'd need to follow to get to the resource you actually wanted.
正如您所注意到的,请求库只考虑 HTTP 响应的另一个方面,不会引发异常。302
例如Found
,HTTP 状态意味着,但响应不包含响应正文,而是包含一个Location
标头,您需要遵循该标头才能访问您实际想要的资源。
So you'll want to look at response.status_code
, and do your handling of that, while catching actual protocol errorswith a try..except
. When catching those you should actually catch requests.exceptions.RequestException
, because this is the base class for all other exceptionsthe requests
module raises.
所以你想看看response.status_code
,做你的是操控性,同时捕捉实际协议错误了try..except
。当捕获那些你应该真正捕获的时候requests.exceptions.RequestException
,因为这是模块引发的所有其他异常的基类requests
。
So here's an example that demonstrates all three cases:
所以这是一个演示所有三种情况的示例:
- Sucessfull
200 OK
response - Sucessful request and response, but status other than
200
- Protocol error (invalid schema)
- 成功
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
Output:
输出:
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'
There could also be an exception raised by response.json()
if you get a sucessfull response, but it simply isn't JSON - so you might want to account for that as well.
response.json()
如果您收到成功的响应,也可能会引发异常,但它根本不是 JSON - 所以您可能也需要考虑到这一点。
Note: The if not response.status_code // 100 == 2
bit works like this:
The //
operator does a so called floor division, so it rounds down to the next integer (this is the default behavior for the /
in Python 2.x, but not Python 3.x, which changed /
to do floating point division). So status // 100 == 2
holds true for all 2xx
codes.
注意:该if not response.status_code // 100 == 2
位的工作方式如下://
运算符执行所谓的floor 除法,因此它向下舍入到下一个整数(这是/
Python 2.x 中的默认行为,但不是 Python 3.x,它更改/
为浮点除法)。因此status // 100 == 2
适用于所有2xx
代码。