for row in handler.find(): parse_data(row) 短短4行代碼,讀取MongoDB里面的每一行數據,然后傳入parse_data做處理。處理完成以后再讀取下一行。邏輯清晰而簡單,能有什么問題?只要parse_data(row)不報錯,這一段代碼就完美無缺。但事實并非這樣。
你的代碼可能會在for row in handler.find()這一行報錯。它的原因,說來話長。要解釋這個問題,我們首先就需要知道,handler.find()返回的并不是數據庫里面的數據,而是一個游標(cursor)對象。
所以pymongo會一次性獲取100行,for row in handler.find()循環第一次的時候,它會連上MongoDB,讀取一百條數據,緩存到內存中。于是第2-100次循環,數據都是直接從內存里面獲取,不會再連接數據庫。 當循環進行到底101次的時候,再一次連接數據庫,再讀取第101-200行內容……,這個邏輯非常有效地降低了網絡I/O耗時。但是,MongoDB默認游標的超時時間是10分鐘。10分鐘之內,必需再次連接MongoDB讀取內容刷新游標時間,否則,就會導致游標超時報錯:
pymongo.errors.CursorNotFound: cursor id 211526444773 not found