2013-10-14 20 views
9

Sto cattura e richieste di stampa Python ConnectionErrors bene con proprio questo:Ottieni Errno dalle richieste Python ConnectionError?

except requests.exceptions.ConnectionError as e: 
    logger.warning(str(e.message)) 

esso stampa messaggi come:

HTTPSConnectionPool(host='10.100.24.16', port=443): Max retries exceeded with url: /api/datastores/06651841-bbdb-472a-bde2-689d8cb8da19 (Caused by <class 'socket.error'>: [Errno 61] Connection refused) 

e

HTTPSConnectionPool(host='10.100.24.16', port=443): Max retries exceeded with url: /api/datastores/06651841-bbdb-472a-bde2-689d8cb8da19 (Caused by <class 'socket.error'>: [Errno 65] No route to host) 

E molti altri. Quello che mi chiedo è, qual è il modo migliore, più Pythoniano, per ottenere quella errno che appare nel messaggio? Mi piacerebbe avere un sistema affidabile per cogliere i problemi e offrire all'utente un messaggio di errore utile e pertinente il più possibile. Per quanto ne so, ConnectionError è un decedent indiretto di BaseException, senza nuove proprietà o metodi aggiunti oltre a quello che offre BaseException. Sono riluttante a usare semplicemente regex perché mi sembra che corro il rischio di assumere che tutti i messaggi di errore siano formattati allo stesso modo in tutte le località.

risposta

23

Penso che sia possibile accedervi utilizzando e.args[0].reason.errno.

Questo è probabilmente documentato da qualche parte, ma di solito quando devo rintracciare qualcosa di simile, lo provo alla console e scavo un po '. (Io uso IPython quindi è facile fare il tab-inspection, ma proviamolo senza).

In primo luogo, cerchiamo di generare un errore utilizzando

import requests 
try: 
    requests.get("http://not.a.real.url/really_not") 
except requests.exceptions.ConnectionError as e: 
    pass 

che dovrebbe dare l'errore in e:

>>> e 
ConnectionError(MaxRetryError("HTTPConnectionPool(host='not.a.real.url', port=80): Max retries exceeded with url: /really_not (Caused by <class 'socket.gaierror'>: [Errno -2] Name or service not known)",),) 

informazioni è di solito in args:

>>> e.args 
(MaxRetryError("HTTPConnectionPool(host='not.a.real.url', port=80): Max retries exceeded with url: /really_not (Caused by <class 'socket.gaierror'>: [Errno -2] Name or service not known)",),) 
>>> e.args[0] 
MaxRetryError("HTTPConnectionPool(host='not.a.real.url', port=80): Max retries exceeded with url: /really_not (Caused by <class 'socket.gaierror'>: [Errno -2] Name or service not known)",) 

Guardando all'interno, vediamo:

>>> dir(e.args[0]) 
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', 
'__getitem__', '__getslice__', '__hash__', '__init__', '__module__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', 
'__str__', '__subclasshook__', '__unicode__', '__weakref__', 'args', 'message', 'pool', 
'reason', 'url'] 

reason sembra incoraggiante:

>>> e.args[0].reason 
gaierror(-2, 'Name or service not known') 
>>> dir(e.args[0].reason) 
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', 
'__getitem__', '__getslice__', '__hash__', '__init__', '__module__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', 
'__str__', '__subclasshook__', '__unicode__', '__weakref__', 'args', 'errno', 'filename', 
'message', 'strerror'] 
>>> e.args[0].reason.errno 
-2 
+0

+1: molto ben fatto! Grazie mille! Ero arrivato a dir (e) ed e.args, ma mi ero fermato a quel punto scambiando gli elementi di e.args in stringhe che avrei dovuto usare regex per estrarre le informazioni che volevo. – ArtOfWarfare

+0

L'uso di un URL falso è stato anche un bel tocco per generare errori. Stavo usando URL reali ma con il mio internet spento ... era scomodo dover andare avanti e indietro tra generare gli errori e ricercarli. – ArtOfWarfare

+0

oh mio signore - grazie grazie - questo errore mi ha fatto impazzire! –