1

I am using socket.gethostbyaddr() in python3 to resolve IP to hostname.

I need to distinguish between 3 cases:

1) success (IP resolved to hostname)
2) IP address has no DNS record
3) DNS server is temporarily unavailable

I am using simple function:

def host_lookup(addr):
    try:
        return socket.gethostbyaddr(addr)[0]
    except socket.herror:
        return None

and then I want to call this function from my main code:

res = host_lookup('45.82.153.76')

if "case 1":
    print('success')
else if "case 2":
    print('IP address has no DNS record')
else if "case 3":
    DNS server is temporarily unavailable
else:
    print('unknown error')

When I try socket.gethostbyaddr() in python console, I get different error codes in each case:

>>> socket.gethostbyaddr('45.82.153.76')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
socket.herror: [Errno 1] Unknown host

and when I deliberatrely make DNS unreachable:

>>> socket.gethostbyaddr('45.82.153.76')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
socket.herror: [Errno 2] Host name lookup failure

So how can I differentiate between these cases in my code above ?

400 the Cat
  • 266
  • 3
  • 23

1 Answers1

1

socket.herror is a subclass of OSError that provides access to the numeric error code errno:

import socket

def host_lookup(addr):
    return socket.gethostbyaddr(addr)[0]

try:
    res = host_lookup("45.82.153.76")
    print('Success: {}'.format(res))
except socket.herror as e:
    if e.errno == 1:
        print('IP address has no DNS record')
    elif e.errno == 2:
        print('DNS server is temporarily unavailable')
    else:
        print('Unknown error')
gparis
  • 1,247
  • 12
  • 32
  • Use `import errno` and the symbolic error codes instead of the numerical ones. Makes the code easier to read and more foolproof. – Patrick Mevzek Nov 13 '19 at 15:34
  • @Patrick Mevzek - can you please show an example, how to use symbolic error codes instead of the numerical ones ? – 400 the Cat Nov 16 '19 at 01:28
  • `import errno; print errno.ENOENT == 2` will show `True`. See https://docs.python.org/3.7/library/errno.html or equivalent for the full list of available variables. – Patrick Mevzek Nov 16 '19 at 03:43
  • However, in this case, the error numbers are not the standard [errno](https://docs.python.org/2/library/errno.html) system symbols but those of [h_errno](https://linux.die.net/man/3/h_errno). It's probably better to declare them yourself: `HOST_NOT_FOUND = 1; TRY_AGAIN = 2; NO_RECOVERY = 3; NO_DATA = 4; NO_ADDRESS = NO_DATA`. – gparis Nov 18 '19 at 09:25