歐拉計畫和其餘編碼競賽常常有最多的運行時間,或者人們吹噓他們的特定解決方案的運行速度。 使用Python時,有時這些方法有些繁瑣-即在__main__
添加計時代碼。 html
剖析Python程序須要花費多長時間的好方法是什麼? python
前一陣子我作了pycallgraph
,它從您的Python代碼生成了可視化效果。 編輯:我已經更新了該示例以使其可用於本文撰寫時的最新版本3.3。 git
pip install pycallgraph
並安裝GraphViz以後,您能夠從命令行運行它: github
pycallgraph graphviz -- ./mypythonscript.py
或者,您能夠分析代碼的特定部分: windows
from pycallgraph import PyCallGraph from pycallgraph.output import GraphvizOutput with PyCallGraph(output=GraphvizOutput()): code_to_profile()
這些都將生成一個pycallgraph.png
文件,相似於下圖: 服務器
是否曾經想知道python腳本到底在作什麼? 輸入檢查外殼。 經過Inspect Shell,您能夠在不中斷正在運行的腳本的狀況下打印/更改全局變量並運行函數。 如今具備自動完成和命令歷史記錄(僅在Linux上)。 app
Inspect Shell不是pdb樣式的調試器。 socket
https://github.com/amoffat/Inspect-Shell ide
您可使用它(和您的手錶)。 svg
@Maxy對這個答案的評論幫助了我不少,我認爲它應該獲得本身的答案:我已經有了cProfile生成的.pstats文件,而且我不想用pycallgraph從新運行,因此我使用了gprof2dot ,而且很漂亮svgs:
$ sudo apt-get install graphviz $ git clone https://github.com/jrfonseca/gprof2dot $ ln -s "$PWD"/gprof2dot/gprof2dot.py ~/bin $ cd $PROJECT_DIR $ gprof2dot.py -f pstats profile.pstats | dot -Tsvg -o callgraph.svg
和布萊姆!
它使用點(pycallgraph使用相同的東西),所以輸出看起來相似。 個人印象是,儘管gprof2dot丟失的信息更少:
值得指出的是,使用探查器僅在主線程上有效(默認狀況下),若是使用其餘線程,則不會從其餘線程得到任何信息。 這可能有點麻煩,由於在探查器文檔中徹底沒有說起。
若是您還想分析線程,則須要查看文檔中的threading.setprofile()
函數 。
您也能夠建立本身的threading.Thread
子類來作到這一點:
class ProfiledThread(threading.Thread): # Overrides threading.Thread.run() def run(self): profiler = cProfile.Profile() try: return profiler.runcall(threading.Thread.run, self) finally: profiler.dump_stats('myprofile-%d.profile' % (self.ident,))
並使用該ProfiledThread
類而不是標準類。 它可能會給您帶來更大的靈活性,可是我不肯定是否值得,特別是若是您使用的是不使用您的類的第三方代碼。
個人方式是使用yappi( https://code.google.com/p/yappi/ )。 與RPC服務器結合使用時特別有用,在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
方法來分析和比較不一樣的程序使用狀況時,尤爲如此。