get open TCP port in Python

Question:

I want to get any random open TCP port on localhost in Python. What is the easiest way?

Asked By: Albert

||

Answers:

My current solution:

def get_open_port():
        import socket
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(("",0))
        s.listen(1)
        port = s.getsockname()[1]
        s.close()
        return port

Not very nice and also not 100% correct but it works for now.

Answered By: Albert

I actually use the following in one of my programs:

port = random.randint(10000,60000)

Of course, this is even more prone to collisions than the code you have. But I’ve never had a problem with it. The point is, at any given time, most of those high-numbered ports are not in use and if you just pick one at random, having a conflict with another process is pretty unlikely. If you do something like the solution you posted in your answer (opening a socket and grabbing its port number), it’s almost certain that the port isn’t going to conflict. So if this is something that you’ll only be using for yourself (as opposed to something you’re going to release to the public), think about whether it’s worth coming up with a truly bulletproof solution. Odds are it’ll never make a difference.

Motivated by Marcelo Cantos’ comment on your question, I will add that the standard solution in cases like this is to have the process that will be using the port bind to it and then share that information with any other program that needs it. Typically it’ll do something like writing a temporary file containing the port number to some standard location in the filesystem. Since the process you’re working with doesn’t do that, in some sense whatever solution you come up with will be a bit of a hack. But again, if it’s just for your own use, that’s probably fine.

Answered By: David Z

This is my version, however its not really random if you specify a port range. This will also suffer from race conditions, but this is the best way I know if you need to know the port ahead of time.

import socket
import errno
import contextlib

reserved_ports = set()

def get_open_port(lowest_port = 0, highest_port = None, bind_address = '', *socket_args, **socket_kwargs):
    if highest_port is None:
        highest_port = lowest_port + 100
    while lowest_port < highest_port:
        if lowest_port not in reserved_ports:
            try:
                with contextlib.closing(socket.socket(*socket_args, **socket_kwargs)) as my_socket:
                    my_socket.bind((bind_address, lowest_port))
                    this_port = my_socket.getsockname()[1]
                    reserved_ports.add(this_port)
                    return this_port
            except socket.error as error:
                if not error.errno == errno.EADDRINUSE:
                    raise
                assert not lowest_port == 0
                reserved_ports.add(lowest_port)
        lowest_port += 1
    raise Exception('Could not find open port')
Answered By: Dave Butler

The ephemeral ports basically lie in range 49152 – 65535.
if you want to check ports in bigger range then just change the values in randint.

import pustil
from random import randint
def getfreeport():
    port = randint(49152,65535)
    portsinuse=[]
    while True:
        conns = pstuil.net_connections()
        for conn in conns:
            portsinuse.append(con.laddr[1])
        if port in portsinuse:
            port = randint(49152,65535)
        else:
            break
    return port
Answered By: Chinmaym

The free port can be found by binding a socket to a port selected by the operating system. After the operating system selects a port the socket can be disposed. However, this solution is not resistant to race conditions – in the short time between getting the free port number and using this port other process may use this port.

import socket

def find_free_port():
    with socket.socket() as s:
        s.bind(('', 0))            # Bind to a free port provided by the host.
        return s.getsockname()[1]  # Return the port number assigned.

https://godbolt.org/z/fs13K13dG

Answered By: Paweł Bylica
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.