我正在编写一个打开文本文件并循环遍历每一行的脚本(在每行之间暂停几秒钟)。对于每一行,它将打开一个临时客户端套接字连接,并将文本发送到主机服务器。主持人的回应可能会也可能不会;无论哪种方式都没关系。
我已经遇到了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)在完成后,是否有更直接的方法确保每个实例都被消除?
答案 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()
来强制垃圾收集。