迭代器冻结

时间:2014-09-12 23:08:22

标签: python python-3.x iterator

我目前正在开发一个python bot,其中我有一些带有迭代器方法的类的代码。

buffer = []
def __iter__(self):
    return self
def __next__(self):
    incoming = str(self.irc.recv(1024), encoding='utf-8').split("\r\n")
    self.buffer += incoming
    last = self.buffer.pop(0) #This implements a FI-FO queue
    #perform operations to extract commands etc.
    return [message,command,trail]

我在迭代器中调用此类,基本上看起来像:

for command in connection: #Connection is the name of the above class
    print(command)

我观察到的是队列的前3个元素被迭代,然后其余的只是留在那里,在队列中,直到新元素进入队列时才被处理,此时队列中的第一个元素离开(好像最后一个元素被推出第一个元素)。 我不确定这是否与迭代器有关,我不应该使用它们来执行此任务(如果没有,那么我应该使用什么),或者这是否是另一个问题。谢谢你的帮助,Kunc。

1 个答案:

答案 0 :(得分:3)

你的主要问题是:

每次推进迭代器时,recv一行或多行,然后return只是最后一行。所以在某些时候,你将把所有的行都堆积在你的队列中,然后尝试接收另一大块数据,这些数据将不会出现,所以你将永远阻止。

想象一下,另一方发送了这三个缓冲区:

'abc\ndef\nghi\n'
'jkl\n'
'mno\nprs\n'

因此,第一次,您将收到'abc\ndef\nghi\n',将其拆分为三行,然后返回'abc'

第二次,您会收到'jkl\n',将其拆分为另一行并追加,然后返回'def'

第三次,您会收到'mno\nprs\n',将其分成另外两行并追加它们,然后返回'ghi'

第四次,你将永远等待接收下一行。

在你不在线之前,你需要做的不是recv


然而,你有第二个问题。绝对没有什么能保证每个缓冲区都以换行结束。所以你可以很容易地将线分成两半。你想做的是这样的:

def __init__(self):
    self.lines, self.buf = [], ''
    # existing code
def __next__(self):
    if not self.lines:
        newbuf = str(self.irc.recv(1024), encoding='utf-8')
        if newbuf:
            self.buf += newbuf
            self.lines = self.buf.split("\r\n")
            self.buf = self.lines.pop()
    last = self.lines.pop(0)
    # etc.

或者,更简单:

def __init__(self):
    # existing code
    self.rfile = self.irc.makefile('r', encoding='utf-8', newline='\r\n')
def close(self):
    self.rfile.close()
    # existing code
def __next__(self):
    return self.rfile.readline()

因为我编写的代码正是socket.makefile所做的,除了它将它包装在一个完整的类文件对象(io.TextIOWrapper中),在这种情况下。)