为什么套接字在列表理解中关闭而不是在 for 循环中?

Why are sockets closed in list comprehension but not in for loop?

我正在尝试在 Python 中创建可用端口列表。我正在关注 this tutorial,但我没有打印打开的端口,而是将它们添加到列表中。

最初,我有如下内容:

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()

# ...

这显然工作正常,但众所周知 comprehensions are faster than loops,所以我现在有:

try:
    available_ports = [port for port in range(1, 8081) if not socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex((remoteServerIP, port))]

# ...

我假设套接字不会关闭,但我用以下方法对其进行了测试:

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()

# ...

确实打印了打开的端口。

为什么comprehension中套接字是closed而不是for循环?我可以依赖这种行为还是转移注意力?

您打开的套接字没有留下任何引用,这意味着它们已被垃圾回收。套接字已关闭 as soon as they are garbage collected.

Python 实现中,列表理解中的套接字被垃圾收集的确切时间不同。 CPython 使用引用计数,因此一旦最后一个引用被删除就关闭套接字。其他实现可能会将关闭推迟到下一个 GC 周期。