天天看點

Python中set、list、dict、tuple的比較

最近使用Concurrence官網中的"ASimple Chat Server"改寫成了一個簡單的遊戲伺服器。

在伺服器長時間營運後,用戶端出現無法連接配接的問題,檢視到運作伺服器的虛拟機卡死在那裡了。剛開始以為是VirtualBox在抽風,不過連續幾天都是這種情況,于是開始懷疑遊戲伺服器出現了記憶體洩漏。

使用"ps-aux | grep python"顯示出伺服器程序CPU和記憶體占用情況,果然内在占用很高,是以斷定出現了記憶體洩漏。仔細審查代碼,并未發現出有什麼漏洞,況且這個伺服器是套用了Concurrence官網的代碼,更不該有問題。

于是寫了個自動執行的用戶端腳本,通過多個用戶端腳本執行大量的轉發操作來檢查洩漏。當我将轉發周期調小至0.001s,并運作3個以上用戶端時檢測到了記憶體洩漏。于是減少控制台輸出,隻顯示用戶端連接配接與斷開的資訊,重新測試,發現有1個連接配接沒能正常關閉。仔細觀察輸出發現有存在一個提示“Nohandlers could be found for logger "SocketServer"”,從網上查到可以通過導入logging子產品來解決。添加後,再次測試,這次顯示出了錯誤異常“setchanged size during iteration”,發生在疊代connected_clients(連接配接用戶端)來轉發資料時,能夠想到這個異常是因為在給使用者轉發消息時有新的連接配接加入或斷開緻使connected_clients發生了改變,我一直以為set和list是一樣的,應該支援在疊代中改變内容。不過通過上網查找到Python中set(集合)是不允許在疊代中改變内容的。是以不應該使用set來儲存連接配接的使用者,換成list就可以了。

這次又給我補了一課,是以就便總結一下Python中set、list、dict、tuple資料類型的比較。

類型 初始化 特性 關于疊代過程中改變内容
set(集合) set() 無序,不可重複 不允許改變
list(清單) list(), [] 有序,可重複 允許改變
dict(字典) dict(), {} 無序,鍵不可重複 不允許,疊代keys()/items()允許
tuple(元組) tuple(), () 有序,可重複,隻讀 永不可變

還有一點,看來官方的"ASimple Chat Server"執行個體使用set來儲存連接配接使用者是有漏洞的,在并發量很大的情況下就會暴露出來。