directedition
directedition

Reputation: 11705

Fast way to test if a port is in use using Python

I have a python server that listens on a couple sockets. At startup, I try to connect to these sockets before listening, so I can be sure that nothing else is already using that port. This adds about three seconds to my server's startup (which is about .54 seconds without the test) and I'd like to trim it down. Since I'm only testing localhost, I think a timeout of about 50 milliseconds is more than ample for that. Unfortunately, the socket.setdefaulttimeout(50) method doesn't seem to work for some reason.

How I can trim this down?

Upvotes: 41

Views: 71535

Answers (8)

RexBarker
RexBarker

Reputation: 1801

Based on answers above, this returns the next free port in the range specified. It is faster than using the sockets module since it doesn't try to connect but uses the OS information instead.

Note: this checks localhost

import psutil
from typing import Optional

def get_next_free_port(
    start_port: int, 
    end_port: Optional[int] = None, 
    check_n_ports: Optional[int] = 10,
) -> int:

    used_ports = [nc.laddr.port for nc in psutil.net_connections()]

    if end_port is None:
        end_port = start_port + check_n_ports

    for port in range(start_port, end_port):
        if port not in used_ports:
            return port

Upvotes: 0

Nickolai
Nickolai

Reputation: 1758

Several of these answers didn't work for me both because I didn't want to interfere with the program using the port I was checking, and also because that program would bind to the port using SO_REUSEADDR which just opens up a big can of worms in which bind can succeed even if the port is in use.

I asked chatGPT for help (not sure if this violates the no-AI assisted answer policy, but I did test this as I will detail below) and it suggested using the psutil library.

Here's the code (it was inspired by the chatGPT output but I also checked the psutil documentation to make sure this was the proper usage and to see if there were better options or any potential issues).

import psutil
import socket

def port_in_use(port):
  for conn in psutil.net_connections():
    if conn.laddr.port == port:
      return True
  return False

This did work for me as expected, and it didn't interfere with the existing program which was my main goal.

Upvotes: 4

Christian Kasim Loan
Christian Kasim Loan

Reputation: 422

Check the available/Used Port

def check_port(port):
    import socket, errno
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:        
        s.bind(("127.0.0.1", port))
    except socket.error as e:
        if e.errno == errno.EADDRINUSE:
            print("Port is already in use", port)
        else:
            print(e)
            print(f"****Port: {port} cannot be acessed****")
            return False
    s.close()
    return True

# Check port open for range of ports
for i in range (10000):
    check_port(i)

Upvotes: 0

Rugnar
Rugnar

Reputation: 3132

To check port use:

def is_port_in_use(port: int) -> bool:
    import socket
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        return s.connect_ex(('localhost', port)) == 0

source: https://codereview.stackexchange.com/questions/116450/find-available-ports-on-localhost

Note: connect_ex cann still raise an exception (in case of bad host name i.e see docs on [1].

[1] https://docs.python.org/3/library/socket.html

Upvotes: 87

Kiran Mali
Kiran Mali

Reputation: 657

Python 2 code to check port is in use or not

# python 2
import socket

def check_port(port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    res = sock.connect_ex(('localhost', port))
    sock.close()
    return res == 0

Check here for python 3

Upvotes: 0

Simon B.
Simon B.

Reputation: 2706

How about just trying to bind to the port you want, and handle the error case if the port is occupied? (If the issue is that you might start the same service twice then don't look at open ports.)

This is the reasonable way also to avoid causing a race-condition, as @eemz said in another answer.

Upvotes: 16

Stian OK
Stian OK

Reputation: 666

Here is an example of how to check if the port is taken.

import socket, errno

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    s.bind(("127.0.0.1", 5555))
except socket.error as e:
    if e.errno == errno.EADDRINUSE:
        print("Port is already in use")
    else:
        # something else raised the socket.error exception
        print(e)

s.close()

Upvotes: 30

Mox
Mox

Reputation: 589

Are you on Linux? If so, perhaps your application could run netstat -lant (or netstat -lanu if you're using UDP) and see what ports are in use. This should be faster...

Upvotes: 2

Related Questions