本文主要介紹3個工具:pdb,objgraph,以及pympler。
1.pdb
pdb是專門用於python代碼調試,模仿gdb。
使用pdb可以查看堆棧,打印變量等。
這里介紹的是命令行下的pdb。
命令行下使用pdb,代碼侵入小,調試方便。
本例中,python安裝在當前目錄下.venv
使用pdb加載python程序
.venv/bin/python -m pdb orange.py
> /Users/lanyang/workspace/orange/orange.py(3)<module>()
-> import inspect
(Pdb)
1
2
3
4
啟動程序
(Pdb)c
1
這樣,python代碼就開始執行了。
相關的命令有
bt 打印堆棧
q 退出
pp 打印變量
c(ont(inue)) 繼續執行
更多命令可參考:
(Pdb) help
Documented commands (type help <topic>):
========================================
EOF c d h list q rv undisplay
a cl debug help ll quit s unt
alias clear disable ignore longlist r source until
args commands display interact n restart step up
b condition down j next return tbreak w
break cont enable jump p retval u whatis
bt continue exit l pp run unalias where
Miscellaneous help topics:
==========================
exec pdb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2.objgraph
安裝objgraph
pip install objgraph
1
查看最常用的類型
(Pdb) import objgraph
(Pdb) objgraph.show_most_common_types(limit=20)
function 22750
dict 15520
tuple 12536
weakref 6679
list 5516
type 3449
getset_descriptor 3408
cell 2566
set 2496
ModuleSpec 1588
module 1582
SourceFileLoader 1502
wrapper_descriptor 1332
builtin_function_or_method 1241
method_descriptor 1219
property 1171
member_descriptor 822
classmethod 697
WeakSet 571
MovedAttribute 501
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
感覺這個函數沒什么用。
查看增長最快的類型
(Pdb) objgraph.show_growth(limit=10)
function 22749 +22749
dict 15515 +15515
tuple 12332 +12332
weakref 6680 +6680
list 5517 +5517
type 3449 +3449
getset_descriptor 3408 +3408
cell 2565 +2565
set 2496 +2496
ModuleSpec 1588 +1588
1
2
3
4
5
6
7
8
9
10
11
show_growth()打印兩次調用之間增加的類型。如果這其中有自己定義的類型,很可能就是問題所在。如果都是python內置類型,可能要花費更多功夫了。
一般排查問題時,在程序開始執行時,調用show_growth(),程序跑一段時間后,再次調用show_growth(),查看哪些對象增長最快。
如果使用pdb在命令行下調試,ctrl+c停止程序的時候,注意觀察上下文,保證跟上次import objgraph時一樣,否則,會出現:
(Pdb) objgraph.show_growth(limit=10)
*** NameError: name 'objgraph' is not defined
(Pdb)
1
2
3
如果出現這個問題,可以繼續讓程序執行,再ctrl+c停止程序。
查看某個類型
(Pdb) objgraph.by_type('list')
1
這個可能會打印一堆。
3.pympler
使用objgraph時,雖然可以看到增長最快的對象,但是無法得知占用內存最多的是哪個。
下面我們就使用pympler,查看內存占用。
(Pdb) from pympler import tracker
(Pdb) tr = tracker.SummaryTracker()
(Pdb) tr.print_diff()
types | # objects | total size
======================= | =========== | ============
<class 'list | 12769 | 1.18 MB
<class 'str | 12769 | 950.47 KB
<class 'int | 2513 | 68.71 KB
<class 'code | 1 | 144 B
function (store_info) | 1 | 136 B
<class 'cell | 2 | 96 B
<class 'tuple | 1 | 64 B
<class 'method | -1 | -64 B
<class 'dict | 0 | -128 B
(Pdb) tr.print_diff()
types | # objects | total size
============== | =========== | ============
<class 'list | 1 | 88 B
<class 'str | 1 | 70 B
(Pdb) tr.print_diff()
types | # objects | total size
======= | =========== | ============
(Pdb)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
tracker對象初始化的時候會創建一個summary,每次調用tracker.print_diff()的時候又會創建一個summary,當前的summary與上次的summary做比較,並打印兩者之間的不同。
4.參考
pdb
objgraph
pympler
pympler muppy
Python內存泄露調試指導思想
使用gc、objgraph干掉python內存泄露與循環引用!
python 進程內存增長問題, 解決方法和工具
————————————————
版權聲明:本文為CSDN博主「翔雲123456」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/lanyang123456/java/article/details/100860904
