2014-09-12 77 views
1

我目前正在開發一個python機器人,其中我有一些帶有迭代器方法的類的代碼。迭代器凍結

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。

+2

'irc.recv'看起來像是可能導致線程阻塞的事情,請確保您沒有等待數據。 – user2085282 2014-09-12 23:51:41

+1

你真的想把'buffer'作爲一個類屬性,由這個類的所有實例共享嗎?對於像這樣的東西,這似乎是一個非常糟糕的主意...... – abarnert 2014-09-13 01:26:44

+1

是的。我現在通過在recv函數中添加if語句來檢查緩衝區是否爲空,然後再添加它。 – Kunc 2014-09-13 01:33:42

回答

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