python 程式碼檢查,實現行級程式碼優化
- 2020 年 1 月 9 日
- 筆記
有時候運行一個python程式,它需要運行很長時間。你或許想提升該程式的運行效率。那該怎麼做那?
首先需要你要找到該程式瓶頸在哪裡~ 比如,哪個函數的運行花費時間比較長? 哪個函數佔用記憶體比較多,是否需要優化對記憶體的使用? 哪個佔用cpu時間比較長? 等… 這些都需要考慮,python有幾個庫可以幫助你解決這些問題~ 廢話不多說,切入主題。
首先寫一段讀取一個文件的python腳本:
touch c9.py #!/usr/bin/env python #Date: 2015/07/21 def read_file(fpath): BLOCK_SIZE=1024 with open(fpath, 'rb') as fd: block = fd.read(BLOCK_SIZE) if block: yield block else: return def main(): for i in read_file('~/access.log') print i if __name__ == "__main__": main()
然後,對該程式碼進行測試。
首先測試該程式碼運行時間:
它是一個外部的python測量。

real 表明了執行腳本花費的總時間。
user 表明了執行腳本花費在cpu的時間。
sys 表明了執行腳本花費在內核函數的時間。
因此, Real time和user+sys相加的不同或許表明了時間花費在等待i/o或者是系統在忙於執行其他任務。
使用cProfile模組
如果想知道花費在每個函數和方法上的時間,以及他們被調用了多少次,你可以使用cProfile模組。
$ python -m cProfile -s cumulative + 要執行的python腳本 ( -s cumulative 它將通過累積花費在每個函數上的時間來排序)

你將看到花費在運行你的腳本總時間是比以前高的,這是我們測量每個函數執行時間的損失。
使用line_profile模組
line_profile 給出了在你程式碼美一行花費cpu時間。
首先需要安裝line_profiler:
pip install line_profiler
接下來,你需要制定你想使用裝飾器@profile評估哪個函數(你不需要把它import 到你的文件中)

接下來測試該程式碼:
$ kernprof -l -v + 要執行的程式碼

-l 標識表明了逐行和-v標識表明詳細輸出。
使用memory_profile模組
memory_profile模組被用於在逐行的基礎上,測量你程式碼的記憶體使用率。儘管如此,它可能使得你的程式碼運行的更慢。
首先安裝memory_profiler
$pip install memory_profiler
也建議安裝psutil包,使得memory_profile模組運行的更快。
$ pip install psutil
類似於line_profile的方式,使用裝飾器@profile來標記哪個函數被跟蹤。
$python -m memory_profiler + 要執行的程式碼文件

看上面的輸出,注意記憶體使用率的單位是MiB,這代表的是兆位元組(1MiB = 1.05MB).
使用guppy模組
使用guppy模組你可以跟蹤每個類型在你程式碼中每個階段(字元、元組、字典等等)有多少對象被創建。
安裝guppy:
$ pip install guppy
然後將你的程式碼該改成如下:
#!/usr/bin/env python from guppy import hpy def read_file(fpath): hp = hpy() print "Heap at the beginning of the functionn", hp.heap() BLOCK_SIZE = 1024 with open(fpath, 'rb') as fd: while True: block = fd.read(BLOCK_SIZE) if block: yield block else: print "Heap at the end of the functionn", hp.heap() return def main(): hp = hpy() print "Heap at the beginning of the functionn", hp.heap() for i in read_file('/Users/David/Applications/py/dt'): #print i pass print "Heap at the end of the functionn", hp.heap() if __name__ == "__main__": main()
執行該程式碼:
$ python c9.py

通過數據結果,可以看出每個str、dict、function等對象被創建。
通過以上幾個模組,可以更加清晰的了解python程式碼的執行過程以及對資源的佔用情況。對程式碼優化有很大的幫助