天天看點

python 代碼檢查,實作行級代碼優化

    有時候運作一個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測量。

python 代碼檢查,實作行級代碼優化

real 表明了執行腳本花費的總時間。

user 表明了執行腳本花費在cpu的時間。

sys 表明了執行腳本花費在核心函數的時間。

是以, Real time和user+sys相加的不同或許表明了時間花費在等待i/o或者是系統在忙于執行其他任務。

使用cProfile子產品

        如果想知道花費在每個函數和方法上的時間,以及他們被調用了多少次,你可以使用cProfile子產品。

$ python -m cProfile -s cumulative  + 要執行的python腳本    ( -s cumulative 它将通過累積花費在每個函數上的時間來排序)

python 代碼檢查,實作行級代碼優化

你将看到花費在運作你的腳本總時間是比以前高的,這是我們測量每個函數執行時間的損失。

使用line_profile子產品

        line_profile 給出了在你代碼美一行花費cpu時間。

        首先需要安裝line_profiler:

                pip install line_profiler

接下來,你需要制定你想使用裝飾器@profile評估哪個函數(你不需要把它import 到你的檔案中)   

python 代碼檢查,實作行級代碼優化

接下來測試該代碼:

        $ kernprof -l -v + 要執行的代碼

python 代碼檢查,實作行級代碼優化

        -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 + 要執行的代碼檔案

python 代碼檢查,實作行級代碼優化

看上面的輸出,注意記憶體使用率的機關是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 function\n", 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 function\n", hp.heap()
                return

def main():
    hp = hpy()
    print "Heap at the beginning of the function\n", hp.heap()
    for i in read_file('/Users/David/Applications/py/dt'):
        #print i
        pass
    print "Heap at the end of the function\n", hp.heap()

if __name__ == "__main__":
    main()      

執行該代碼:

$ python c9.py

python 代碼檢查,實作行級代碼優化