I'm trying to create a list of available ports in Python. I am following this tutorial, but instead of printing the open ports, I'm adding them to a list.
Initially, I had something like the following:
available_ports = []
try:
for port in range(1,8081):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((remoteServerIP, port))
if result == 0:
available_ports.append(port)
sock.close()
# ...
This clearly works fine, but it is well known that comprehensions are faster than loops, so I now have:
try:
available_ports = [port for port in range(1, 8081) if not socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex((remoteServerIP, port))]
# ...
I assumed the sockets wouldn't be closed, but I tested it with the following:
try:
available_ports = [port for port in range(1, 8081) if not socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex((remoteServerIP, port))]
for port in range(1,8081):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((remoteServerIP, port))
if result == 0:
print("Port {}: \t Open".format(port))
sock.close()
# ...
and indeed the open ports were printed.
Why are the sockets closed in the comprehension but not the for loop? Can I rely on this behavior or is this a red herring?
There are no references left to your opened sockets, which means they are garbage collected. Sockets are closed as soon as they are garbage collected.
Exactly when the sockets from your list comprehension are garbage collected differs between Python implementations. CPython uses reference counting and therefore closes the sockets as soon as the last reference is dropped. Other implementations might defer the closing to the next GC cycle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With