Reputation: 11705
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
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
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
Reputation: 422
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
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
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
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
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
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