而當Object的reference count減至0的時候,Python的GC會找時間把這些Object清除掉。
對Python而言,memory leak產生的可能性有兩種
- Circular reference
- Referece在global的變數或是module上
其實有些tool可以找到這種reference的關係,這邊介紹的是 objgraph - 官網,視覺化的Reference結果圖,讓人一目瞭然。
可以在下載後安裝
pip install objgraph
或是直接將壓縮檔內的objgraph.py解壓放在執行檔旁,因為objgraph就這麼一個檔案!
不過,為了將objgraph解析後的狀態轉成圖檔,還需要安裝另一個tool - graphviz,這個是跟python無關的tool,只是objgraph輸出一個config檔,透過subprocess執行graphviz去讀取這個config檔,然後輸出最後關係圖的圖檔。接著可以透過關係圖檔找到應該解除reference link的地方,再一一破解,應該就可以解開memory leak了。
以下示範較常用的show_backrefs()
還有其他的API可直接參照objgraph.py裡
Reference:
以下示範較常用的show_backrefs()
還有其他的API可直接參照objgraph.py裡
Example: Value object reference 在 Container 裡
class Value(object):
def __init__(self, v):
object.__init__(self)
self.v = v
def get(self):
return self.v
def set(self, v):
self.v = v
class Container(object):
def __init__(self):
object.__init__(self)
self.children = []
def get(self, idx):
return self.children[idx]
def pop(self):
c = self.children.pop()
return c
def push(self, c):
return self.children.append(c)
if __name__== '__main__':
c1 = Container()
c1.push(Value(100))
import objgraph
objgraph.show_backrefs([c.get(0)], filename='test.png')
輸出結果圖:Example 2: 2個Container同時reference在同一個Value object
if __name__== '__main__':
c1 = Container()
c1.push(Value(100))
c2 = Container()
c2.push(c1.get(0))
import objgraph
objgraph.show_backrefs([c.get(0)], filename='test.png')
輸出結果圖:Example 3: circular reference
if __name__== '__main__':
c1 = Container()
v = Value(c1)
c1.push(v) #circular reference
import objgraph
objgraph.show_backrefs([c1.get(0)], max_depth=5, filename='test.png')
輸出結果圖:Reference:
- objgraph - official site
- graphviz - offcial site
- PyPI - objgraph



沒有留言:
張貼留言