Python script to collect all hostnames of ip addresses with only prime entities
Question: I have a Python script to collect hostnames of ip address with primes as byte
entities. E.g., 211.13.17.2 is a valid ip according to my problem set where
every byte entity(decimal representation) is a prime.

**Code:**

    
    
    from itertools import product
    import socket
    
    
    # prime or not
    def prime(n):
        if n > 1:
            p = 0
            for i in range(2, n-1):
                if divmod(n, i)[1] == 0:
                    p = 1
                    break
            if p == 0:
                return True
    
    
    def get_host_name(b1, b2, b3, b4):
        addr = str(b1) + '.' + str(b2) + '.' + str(b3) + '.' + str(b4)
        try:
            return socket.gethostbyaddr(addr)
        except socket.herror:
            pass
    
    
    # find host names whose ip addresses are all primes
    byte = [b for b in range(0, 256) if prime(b)]
    ips = list(product(byte, byte, byte, byte))
    print 'Total ips = ', len(ips)
    
    for ip in ips:
        if get_host_name(*ip):
            print get_host_name(*ip)
    

The problem is my script is too slow. I need expert help to optimize this
code. Please pinpoint all mistakes and ways to make it behave faster.


Answer: for the prime numbers, you can use something like this,

    
    
    import numpy as np
    isprime = lambda x: np.all(np.mod(x, range(2, 1 + int(np.sqrt(x)))))
    primes = np.array([ x for x in range(2, 255) if isprime(x) ])
    

and you can have a generator for ip addresses by

    
    
    ('{}.{}.{}.{}'.format(*x) for x in itertools.product(primes, repeat=4))
    

but most likely the code is slow in the `socket` part, and because of the
number of combinations that it needs to check; for that you may _try_
parallelism, by using a pool of worker processes; something like this:

    
    
    from multiprocessing import Pool
    from socket import gethostbyaddr
    
    def gethost(addr):
        try:
            return gethostbyaddr(addr)
        except:
            pass
    
    if __name__ == '__main__':
    
        p = Pool(3)
        print (p.map(gethost,['74.125.228.137',
                              '11.222.333.444',
                              '17.149.160.49',
                              '98.139.183.24']))
    

**edit** : for only prime numbers less than 50, (50K+ combinations) and 20
worker processes it takes almost 6 minutes on my machines and it finds 16K+
results. so, with this huge number of combinations parallelism cannot help
much.

