重复的瞬态套接字连接 - 内存泄漏风险?

时间:2012-12-29 13:28:29

标签: python sockets memory-leaks

我正在编写一个打开文本文件并循环遍历每一行的脚本(在每行之间暂停几秒钟)。对于每一行,它将打开一个临时客户端套接字连接,并将文本发送到主机服务器。主持人的回应可能会也可能不会;无论哪种方式都没关系。

我已经遇到了Python套接字限制,你无法重新连接现有的套接字对象(因为这样做会触发异常EBADF, 'Bad file descriptor')。所以我正在为每个瞬态连接创建一个新的套接字实例。当然,诀窍就是如何避免内存泄漏。

我接近这个的方法是将创建,使用和关闭套接字的整个部分推送到一个函数 - 依赖Python的垃圾收集来删除每个实例后我完成它:

    import socket,select,time

    def transientConnect(host,port,sendData):
        response = ''
        sendSocket = socket.socket()
        sendSocket.connect((serverHost,serverPort))
        sendSocket.send(line)
        gotData = select.select([sendSocket],[],[],2)
        if (gotData[0]):response = sendSocket.recv(65535)
        sendSocket.close()
        return response

    scriptLines = open('testScript.txt','r').readlines()
    serverHost  = '127.0.0.1'
    serverPort  = 15004
    for line in scriptLines:
        response = transientConnect(serverHost,serverPort,line)
        print(response)
        time.sleep(3.0)

我的问题:(1)这种方法是否可以避免任何内存泄漏? (2)在完成后,是否有更直接的方法确保每个实例都被消除?

1 个答案:

答案 0 :(得分:4)

首先,仅使用套接字进行单次交换是正常的。请参阅socket HOWTO

python的一个好处是,通常你不必担心垃圾收集。除非你有真正的记忆使用问题,否则你不应该这样做。

this webpage开始,请记住:

  

“当超出范围时,Python不会清理对象。当最后一次引用超出范围时,它会清理它。”

因此,如果在函数内部创建的套接字未在其他地方引用,则它应该超出范围并被释放(但不是gc-ed)。以下内容可能与cpython有关。阅读gc.set_threshold()的文档,了解垃圾收集在cpython中的工作原理。特别是:

  

“当分配数量减去解除分配数量超过 threshold0 时,集合开始。”

阈值的标准值(以cpython为单位)为:

In [2]: gc.get_threshold()
Out[2]: (700, 10, 10)

因此,在获得gc运行之前,会有相当数量的分配。您可以通过运行gc.collect()强制垃圾收集。