I'm catching and printing Python Requests ConnectionErrors fine with just this:
except requests.exceptions.ConnectionError as e:
logger.warning(str(e.message))
It prints out messages such as:
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)
and
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)
And many others. What I'm wondering is, what's the best, most Pythonic, way to get that errno that's displaying in the message? I'd like to have a reliable system for catching the issues and offering as helpful and relevant error message to the user as possible. As far as I can tell, ConnectionError is an indirect decedent of BaseException, with no new properties or methods being added beyond what BaseException offers. I'm hesitant to simply use regex because it seems to me I run the risk of assuming all error messages are formatted the same way in all localities.
I think you can access it using e.args[0].reason.errno
.
This is probably documented somewhere, but usually when I have to track down something like this I just try it at the console and dig around a little bit. (I use IPython so it's easy to do tab-inspection, but let's try it without).
First, let's generate an error using
import requests
try:
requests.get("http://not.a.real.url/really_not")
except requests.exceptions.ConnectionError as e:
pass
which should give us the error 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)",),)
Information is usually 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)",)
Looking inside, we see:
>>> 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
looks encouraging:
>>> 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
I had troubles getting the same results with python 3.6 and requests 2.18. I managed to get the errno using the http
and socket
modules :
import socket, html
try:
http.client.HTTPConnection('invalid').connect()
except (socket.gaierror, ConnectionError) as e:
print(e.errno)
Hopefully it helps someonelse.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With