Попробуйте/за исключением использования модуля запросов Python
выполнение некоторого тестирования 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 ответов
если вы хотите, чтобы ответ вызвал исключение для кода состояния не-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
или TimeoutError
s, etc. Ни одно из них не означает то же самое, что ты пытаешься поймать.
Примечание: даже если это принятый ответ, вы должны скорее пойти с response.raise_for_status()
как описано в Иэн ниже (он один из операторов requests
модуль).
как вы справляетесь с этим, зависит от того, что вы считаете ошибкой HTTP. Есть коды состояния, но не все, кроме 200
обязательно означает, что есть ошибка какая-то.
как вы заметили, библиотека запросов рассматривает их как еще один аспект HTTP-ответа и не вызывает исключения. Состояния HTTP 302
, например,Found
, но ответ не содержит ответа, но Location
заголовок вместо этого вам нужно будет следовать, чтобы добраться до ресурса, который вы действительно хотели.
так что вы хотите посмотреть на response.status_code
, и сделайте свою обработку этого, поймав фактический ошибки протокола С try..except
. Когда вы ловите тех, кого вы должны на самом деле поймать requests.exceptions.RequestException
, потому что это базовый класс для всех исключений the requests
модуль поднимает.
Итак, вот пример, который демонстрирует все три случая:
- продвижение
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
бит работает следующим образом:
The //
оператор делает так называемый этаж отдел, так что округление до следующего целого числа (это поведение по умолчанию для /
в Python 2.x, но не Python 3.x, который изменился /
для деления с плавающей запятой). Так что status // 100 == 2
держит верно для всех 2xx
кодексы.
Вы можете проверить response.status_code
значение. Если это не 200
, тогда вы можете считать это условием ошибки и создать собственное исключение.