我目前正在开发一个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。
答案 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
中),在这种情况下。)