[python] 你如何描述腳本?


10 Answers

pycallgraph時間我做了pycallgraph ,它可以從你的Python代碼生成一個可視化文件。 編輯:我已經更新了示例以使用最新版本。

pip install pycallgraph並安裝GraphViz您可以從命令行運行它:

pycallgraph graphviz -- ./mypythonscript.py

或者,您可以配置代碼的特定部分:

from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput

with PyCallGraph(output=GraphvizOutput()):
    code_to_profile()

這些都會生成一個pycallgraph.png文件,類似於下面的圖片:

Question

歐拉項目和其他編碼競賽往往有最大的時間來運行,或者人們吹噓他們的特定解決方案的運行速度。 使用python,有時候這些方法有點奇怪 - 即將時序代碼添加到__main__

什麼是一個好的方法來分析一個python程序需要運行多久?




python wiki是分析資源的絕佳頁面: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code : http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code

正如python文檔一樣: http : //docs.python.org/library/profile.html

如Chris Lawlor所示cProfile是一個很好的工具,可以輕鬆用於打印到屏幕上:

python -m cProfile -s time mine.py <args>

或者提交:

python -m cProfile -o output.file mine.py <args>

PS>如果您使用的是Ubuntu,請確保安裝python-profile

sudo apt-get install python-profiler 

如果你輸出到文件,你可以使用以下工具獲得很好的可視化效果

PyCallGraph:創建通話圖形圖像的工具
安裝:

 sudo pip install pycallgraph

跑:

 pycallgraph mine.py args

視圖:

 gimp pycallgraph.png

你可以使用任何你喜歡的來查看png文件,我用gimp
不幸的是我經常得到

點:圖形對於cairo-renderer位圖來說太大。 按0.257079縮放以適合

這使得我的圖像變得非常小。 所以我通常創建svg文件:

pycallgraph -f svg -o pycallgraph.svg mine.py <args>

PS>確保安裝graphviz(提供點程序):

sudo pip install graphviz

使用gprof2dot通過@maxy / @quodlibetor進行替代圖形化:

sudo pip install gprof2dot
python -m cProfile -o profile.pstats mine.py
gprof2dot -f pstats profile.pstats | dot -Tsvg -o mine.svg



pprofile

line_profiler (這裡已經介紹過)也啟發了pprofile ,它被描述為:

行粒度,線程感知確定性和統計純python分析器

它提供line_profiler行粒度,是純Python,可以用作獨立命令或模塊,甚至可以生成可通過[k|q]cachegrind輕鬆分析的callgrind格式文件。

vprof

還有一個vprof ,一個Python包,描述如下:

為各種Python程序特性(如運行時間和內存使用情況)提供豐富且交互式的可視化。




當我不在服務器上的根目錄時,我使用lsprofcalltree.py並像這樣運行我的程序:

python lsprofcalltree.py -o callgrind.1 test.py

然後我可以用任何與callgrind兼容的軟件打開報告,例如qcachegrind




cProfile非常適合快速剖析,但大多數情況下它都會以錯誤結尾。 函數runctx通過正確地初始化環境和變量來解決這個問題,希望它對於某人有用:

import cProfile
cProfile.runctx('foo()', None, locals())



研究此主題時,我遇到了一個名為SnakeViz的方便工具。 SnakeViz是一個基於Web的概要分析可視化工具。 這是非常容易安裝和使用。 我使用它的通常方法是用%prun生成一個stat文件,然後在SnakeViz中進行分析。

所使用的主要技術是Sunburst圖表 ,如下所示,其中函數調用的層次結構安排為以角度寬度編碼的弧形和時間信息層。

最好的事情是你可以與圖表互動。 例如,放大一個可以點擊一個弧線,並且弧線及其後代將被放大為一個新的陽光來顯示更多細節。




在Virtaal的source有一個非常有用的類和裝飾器,可以使分析(即使是特定的方法/函數)非常簡單。 然後可以在KCacheGrind中非常舒適地查看輸出。




我的方法是使用yappi( https://code.google.com/p/yappi/ )。 與RPC服務器結合使用(甚至只是為了調試),您可以註冊方法來啟動,停止和打印分析信息,例如以這種方式:

@staticmethod
def startProfiler():
    yappi.start()

@staticmethod
def stopProfiler():
    yappi.stop()

@staticmethod
def printProfiler():
    stats = yappi.get_stats(yappi.SORTTYPE_TTOT, yappi.SORTORDER_DESC, 20)
    statPrint = '\n'
    namesArr = [len(str(stat[0])) for stat in stats.func_stats]
    log.debug("namesArr %s", str(namesArr))
    maxNameLen = max(namesArr)
    log.debug("maxNameLen: %s", maxNameLen)

    for stat in stats.func_stats:
        nameAppendSpaces = [' ' for i in range(maxNameLen - len(stat[0]))]
        log.debug('nameAppendSpaces: %s', nameAppendSpaces)
        blankSpace = ''
        for space in nameAppendSpaces:
            blankSpace += space

        log.debug("adding spaces: %s", len(nameAppendSpaces))
        statPrint = statPrint + str(stat[0]) + blankSpace + " " + str(stat[1]).ljust(8) + "\t" + str(
            round(stat[2], 2)).ljust(8 - len(str(stat[2]))) + "\t" + str(round(stat[3], 2)) + "\n"

    log.log(1000, "\nname" + ''.ljust(maxNameLen - 4) + " ncall \tttot \ttsub")
    log.log(1000, statPrint)

然後,當你的程序工作時,你可以通過調用startProfiler RPC方法並通過調用printProfiler (或者修改rpc方法將它返回給調用者)將日誌文件信息轉儲到日誌文件來隨時啟動分析器,並獲得如下輸出:

2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
name                                                                                                                                      ncall     ttot    tsub
2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
C:\Python27\lib\sched.py.run:80                                                                                                           22        0.11    0.05
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\xmlRpc.py.iterFnc:293                                                22        0.11    0.0
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\serverMain.py.makeIteration:515                                                    22        0.11    0.0
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\PicklingXMLRPC.py._dispatch:66                                       1         0.0     0.0
C:\Python27\lib\BaseHTTPServer.py.date_time_string:464                                                                                    1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py._get_raw_meminfo:243     4         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.decode_request_content:537                                                                          1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py.get_system_cpu_times:148 4         0.0     0.0
<string>.__new__:8                                                                                                                        220       0.0     0.0
C:\Python27\lib\socket.py.close:276                                                                                                       4         0.0     0.0
C:\Python27\lib\threading.py.__init__:558                                                                                                 1         0.0     0.0
<string>.__new__:8                                                                                                                        4         0.0     0.0
C:\Python27\lib\threading.py.notify:372                                                                                                   1         0.0     0.0
C:\Python27\lib\rfc822.py.getheader:285                                                                                                   4         0.0     0.0
C:\Python27\lib\BaseHTTPServer.py.handle_one_request:301                                                                                  1         0.0     0.0
C:\Python27\lib\xmlrpclib.py.end:816                                                                                                      3         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.do_POST:467                                                                                         1         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.is_rpc_path_valid:460                                                                               1         0.0     0.0
C:\Python27\lib\SocketServer.py.close_request:475                                                                                         1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\__init__.py.cpu_times:1066               4         0.0     0.0 

對於短腳本來說它可能不是很有用,但有助於優化服務器類型的進程,特別是考慮到printProfiler方法可以隨時調用多次來分析和比較不同的程序使用場景。




我認為cProfile非常適合分析,而kcachegrind非常適合可視化結果。 pyprof2calltree處理文件轉換。

python -m cProfile -o script.profile script.py
pyprof2calltree -i script.profile -o script.calltree
kcachegrind script.calltree

要安裝所需的工具(至少在Ubuntu上):

apt-get install kcachegrind
pip install pyprof2calltree

結果:




還有一個名為statprof的統計分析器。 它是一個採樣分析器,因此它為您的代碼增加了最小的開銷,並且提供了基於行的(而不僅僅是基於函數的)時序。 它更適合於像遊戲這樣的軟實時應用程序,但可能比cProfile的精度要低。

statprofstatprof ,所以可以通過指定git存儲庫來使用pip進行安裝:

pip install git+git://github.com/bos/statprof.py@1a33eba91899afe17a8b752c6dfdec6f05dd0c01

你可以像這樣運行它:

import statprof

with statprof.profile():
    my_questionable_function()

另請參閱https://.com/a/10333592/320036







Related