Richtiger Weg, um zu versuchen / außer mit Python-Anforderungsmodul?

Antworten:

792

Schauen Sie sich die Ausnahmedokumente für Anfragen an . Zusamenfassend:

Bei einem Netzwerkproblem (z. B. DNS-Fehler, verweigerte Verbindung usw.) lösen Anfragen eine ConnectionErrorAusnahme aus.

Im Falle der seltenen ungültigen HTTP-Antwort lösen Anfragen eine HTTPErrorAusnahme aus.

Wenn eine Anforderung abgelaufen ist, wird eine TimeoutAusnahme ausgelöst.

Wenn eine Anforderung die konfigurierte Anzahl maximaler Umleitungen überschreitet, wird eine TooManyRedirectsAusnahme ausgelöst.

Alle Ausnahmen, die Requests explizit auslösen, erben von requests.exceptions.RequestException.

Um Ihre Frage zu beantworten, wird das, was Sie zeigen, nicht alle Ihre Grundlagen abdecken. Sie werden nur verbindungsbezogene Fehler abfangen, keine, bei denen eine Zeitüberschreitung auftritt.

Was zu tun ist, wenn Sie die Ausnahme abfangen, hängt wirklich vom Design Ihres Skripts / Programms ab. Ist es akzeptabel zu beenden? Können Sie es erneut versuchen? Wenn der Fehler katastrophal ist und Sie nicht weitermachen können, können Sie Ihr Programm abbrechen, indem Sie SystemExit auslösen (eine gute Möglichkeit, einen Fehler zu drucken und aufzurufen sys.exit).

Sie können entweder die Basisklassenausnahme abfangen, die alle Fälle behandelt:

try:
    r = requests.get(url, params={'s': thing})
except requests.exceptions.RequestException as e:  # This is the correct syntax
    raise SystemExit(e)

Oder Sie können sie separat fangen und verschiedene Dinge tun.

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)

Wie Christian betonte:

Wenn Sie möchten, dass http-Fehler (z. B. 401 Unauthorized) Ausnahmen auslösen, können Sie anrufen Response.raise_for_status. Das wird einen HTTPErrorauslösen, wenn die Antwort ein http-Fehler war.

Ein Beispiel:

try:
    r = requests.get('http://www.google.com/nothere')
    r.raise_for_status()
except requests.exceptions.HTTPError as err:
    raise SystemExit(err)

Wird drucken:

404 Client Error: Not Found for url: http://www.google.com/nothere
Jonathon Reinhart
quelle
11
Sehr gute Antwort für den Umgang mit den Besonderheiten der Anforderungsbibliothek und auch für das allgemeine Auffangen von Ausnahmen.
Brian Peterson
10
Beachten Sie, dass Sie aufgrund eines Fehlers in der zugrunde liegenden urllib3-Bibliothek auch socket.timeoutAusnahmen abfangen müssen, wenn Sie eine Zeitüberschreitung verwenden: github.com/kennethreitz/requests/issues/1236
jb.
15
Zukünftige Kommentarleser: Dies wurde in Requests 2.9 (das urllib3 1.13 bündelt)
RazerM
14
Wenn Sie möchten, dass http-Fehler (z. B. 401 Unauthorized) Ausnahmen auslösen, können Sie Response.raise_for_status aufrufen . Dies löst einen HTTPError aus, wenn die Antwort ein http-Fehler war.
Christian Long
5
Die Ausnahmeliste auf der Anforderungswebsite ist nicht vollständig. Die vollständige Liste können Sie hier lesen .
Epoc
86

Ein zusätzlicher Vorschlag, um explizit zu sein. Es scheint am besten, von spezifisch zu allgemein zu wechseln, um den gewünschten Fehler zu erhalten, damit die gewünschten Fehler nicht durch den allgemeinen Fehler maskiert werden.

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
Jouell
quelle
Ist diese Syntax auch für Post gültig?
ScipioAfricanus
@ ScipioAfricanus ja.
Andrea
10

Das Ausnahmeobjekt enthält auch die ursprüngliche Antwort e.response. Dies kann hilfreich sein, wenn der Fehler als Antwort vom Server angezeigt werden muss. Zum Beispiel:

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)
tsh
quelle