# Find available ports on localhost

I'm writing code to find the available ports on 127.0.0.1. I'd like it to be faster, but it's functional now.

def find_open_ports():
for port in xrange(1,8081):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
res = sock.connect_ex(('localhost', port))
if res == 0:
yield port
sock.close()


and it is called with available_ports = list(find_open_ports()).

There is no error handling because this will be running server-side. If localhost can't be found, there are bigger problems than failing a port scan.

It's always good to use a context manager always. You can wrap the socket in contextlib.closing().

I know your question is tagged specifically , but I suggest to use range instead of xrange anyway, because you don't really lose anything with it, and the script becomes compatible with Python 3.

from contextlib import closing
import socket

def find_open_ports():
for port in range(1, 8081):
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
res = sock.connect_ex(('localhost', port))
if res == 0:
yield port


Note that in Python 3 you wouldn't need closing, you could write simply:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:

• I always assumed xrange would be faster than range because xrange is a generator instead of a list? – erip Jan 11 '16 at 17:54
• It depends. In any case, range will not be your bottleneck here, because it will be far outweighed by network I/O – janos Jan 11 '16 at 17:56

2. You're only checking the IPv4 definition of 'localhost'. We live in the future! IPv6 calls localhost ::1. At first blush, this would seem to not matter - something's either listening or not, right? - but it turns out that firewalls sometimes have different rulesets for IPv4 vs IPv6, so one may get through but the other not. You didn't specify what this code was for, so it's just a caveat to keep in mind.