Правильный способ попробовать / кроме использования модуля запросов Python?

try:
    r = requests.get(url, params={'s': thing})
except requests.ConnectionError, e:
    print e #should I also sys.exit(1) after this?

Это верно? Есть ли лучший способ структурировать это? Покроет ли это все мои базы?


person John Smith    schedule 12.05.2013    source источник


Ответы (3)


Ознакомьтесь с документами об исключениях запросов. Суммируя:

В случае проблем с сетью (например, сбой DNS, отказ в соединении и т. Д.) Запросы вызовут исключение ConnectionError.

В случае редкого недействительного ответа HTTP запросы вызывают исключение 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)

Как отметил Кристиан:

Если вы хотите, чтобы ошибки http (например, 401 Unauthorized) вызывали исключения, вы можете вызвать Response.raise_for_status. Это вызовет HTTPError, если ответом была ошибка 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
person Jonathon Reinhart    schedule 12.05.2013
comment
Очень хороший ответ для работы со спецификой библиотеки запросов, а также для общего перехвата исключений. - person Brian Peterson; 27.06.2014
comment
Обратите внимание, что из-за ошибки в базовой библиотеке urllib3 вам также необходимо перехватить socket.timeout исключения, если вы используете тайм-аут: github.com/kennethreitz/requests/issues/1236 - person jb.; 21.08.2014
comment
Будущие читатели комментариев: это было исправлено в Requests 2.9 (который связывает urllib3 1.13). - person RazerM; 19.07.2016
comment
Если вы хотите, чтобы ошибки http (например, 401 Unauthorized) вызывали исключения, вы можете вызвать Response.raise_for_status. Это вызовет ошибку HTTPError, если ответом была ошибка http. - person Christian Long; 17.08.2016
comment
Спасибо @ChristianLong. Я добавил эту отличную информацию к своему ответу. - person Jonathon Reinhart; 18.08.2016
comment
Список исключений на веб-сайте запросов не является полным. Вы можете прочитать полный список здесь. - person Epoc; 31.01.2017
comment
Есть ли способ распечатать настраиваемое сообщение об ошибке, когда r.raise_for_status() возвращает ошибку? Сообщение по умолчанию довольно пугающее, и я хотел бы дать пользователю несколько советов о том, как избежать ответов об ошибках. - person user5359531; 27.04.2017
comment
@ user5359531 Конечно. Обрабатывайте разные исключения и print разные сообщения для каждого из них. - person Jonathon Reinhart; 27.04.2017
comment
Отличный ответ! Другая возможность, если вы используете функцию urllib3 для повторной попытки по определенным кодам возврата, - это requests.exceptions.RetryError. Чтобы выполнить повторные попытки, но избежать необходимости перехватывать сбои, см. stackoverflow.com/questions/43481165/ - person nealmcb; 17.10.2017
comment
проголосовали за! Итак, допустим, что этот вызов api выполняется внутри метода, который в основном является вашей оболочкой API, что вы делаете? вернуть исключение из предложения except для обработки на более высоком уровне, использовать logger.warn или что-то в этом роде? напечатать строковое сообщение, которое я считаю неправильным способом делать что-то - person PirateApp; 14.07.2018
comment
@PirateApp Хороший вопрос. Это зависит от вас, но я бы обернул и повторно поднял исключения запросов. Библиотека не должна записывать диагностическую информацию в stdout / stderr. Взгляните на некоторые другие обертки API, такие как python-gitlab. - person Jonathon Reinhart; 14.07.2018

Еще одно уточнение. Кажется, лучше всего перейти от конкретных к общим ошибкам, чтобы получить желаемую ошибку, которую нужно отловить, чтобы конкретные ошибки не маскировались общей.

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

vs

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
person jouell    schedule 30.10.2017
comment
это допустимый синтаксис и для сообщения? - person ScipioAfricanus; 22.05.2019
comment
@ScipioAfricanus да. - person andrea; 23.06.2019

Объект исключения также содержит исходный ответ 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)
person tsh    schedule 24.09.2019