欧拉计画和其余编码竞赛常常有最多的运行时间,或者人们吹嘘他们的特定解决方案的运行速度。 使用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
方法来分析和比较不一样的程序使用状况时,尤为如此。