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


Відповіді:


794

Ознайомтеся з документами щодо виключень Запити . Коротко:

У разі виникнення проблеми з мережею (наприклад, збій 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_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

11
Дуже хороша відповідь для розгляду специфіки бібліотеки запитів, а також загального вибору винятків.
Брайан Петерсон

10
Зверніть увагу, що через помилку в нижній бібліотеці urllib3 вам також потрібно буде вилучити socket.timeoutвинятки, якщо ви використовуєте timeout: github.com/kennethreitz/requests/isissue/1236
jb.

15
Майбутні читачі коментарів: це було зафіксовано у Запити 2.9 (які входять до групи urllib3 1.13)
RazerM

14
Якщо ви хочете, щоб http-помилки (наприклад, 401 Несанкціоноване) викликали винятки, ви можете зателефонувати на Response.raise_for_status . Це призведе до виникнення HTTPError, якщо відповідь була помилкою http.
Крістіан Лонг

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

чи дійсний цей синтаксис і для публікації?
ScipioAfricanus

@ScipioAfricanus так.
Андреа

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.