Project Euler和其他编码竞赛通常有最长的运行时间,或者人们吹嘘他们的特定解决方案运行速度有多快。对于Python,有时方法有些笨拙——即向__main__添加计时代码。

描述Python程序运行时间的好方法是什么?


当前回答

想知道python脚本到底在做什么吗?输入检查外壳。Inspect Shell允许您打印/更改全局并运行函数,而不中断正在运行的脚本。现在有了自动完成和命令历史记录(仅在linux上)。Inspect Shell不是pdb样式的调试器。

https://github.com/amoffat/Inspect-Shell

你可以用它(还有你的手表)。

其他回答

还值得一提的是GUI cProfile转储查看器RunSnakeRun。它允许您排序和选择,从而放大程序的相关部分。图片中矩形的大小与所用时间成正比。如果您将鼠标悬停在一个矩形上,它将突出显示表中的调用以及地图上的任何位置。双击矩形时,它会放大该部分。它将显示谁调用了该部分以及该部分调用了什么。

描述性信息非常有用。它向您显示了该位的代码,当您处理内置库调用时,该代码会很有用。它告诉要查找代码的文件和行。

还想指出,OP说的是“剖析”,但似乎他是指“时机”。请记住,程序在评测时运行速度会变慢。

我刚刚从pypref_time中开发了自己的分析器:

https://github.com/modaresimr/auto_profiler

更新版本2

安装:

pip install auto_profiler

快速入门:

from auto_profiler import Profiler

with Profiler():
    your_function()

在Jupyter中使用,可以实时查看已用时间

更新版本1

通过添加装饰器,它将显示一个耗时的函数树

@探查器(深度=4)

Install by: pip install auto_profiler

实例

import time # line number 1
import random

from auto_profiler import Profiler, Tree

def f1():
    mysleep(.6+random.random())

def mysleep(t):
    time.sleep(t)

def fact(i):
    f1()
    if(i==1):
        return 1
    return i*fact(i-1)

def main():
    for i in range(5):
        f1()

    fact(3)


with Profiler(depth=4):
    main()

示例输出


Time   [Hits * PerHit] Function name [Called from] [function location]
-----------------------------------------------------------------------
8.974s [1 * 8.974]  main  [auto-profiler/profiler.py:267]  [/test/t2.py:30]
├── 5.954s [5 * 1.191]  f1  [/test/t2.py:34]  [/test/t2.py:14]
│   └── 5.954s [5 * 1.191]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
│       └── 5.954s [5 * 1.191]  <time.sleep>
|
|
|   # The rest is for the example recursive function call fact
└── 3.020s [1 * 3.020]  fact  [/test/t2.py:36]  [/test/t2.py:20]
    ├── 0.849s [1 * 0.849]  f1  [/test/t2.py:21]  [/test/t2.py:14]
    │   └── 0.849s [1 * 0.849]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
    │       └── 0.849s [1 * 0.849]  <time.sleep>
    └── 2.171s [1 * 2.171]  fact  [/test/t2.py:24]  [/test/t2.py:20]
        ├── 1.552s [1 * 1.552]  f1  [/test/t2.py:21]  [/test/t2.py:14]
        │   └── 1.552s [1 * 1.552]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
        └── 0.619s [1 * 0.619]  fact  [/test/t2.py:24]  [/test/t2.py:20]
            └── 0.619s [1 * 0.619]  f1  [/test/t2.py:21]  [/test/t2.py:14]

Scalene是一个新的python分析器,它涵盖了许多用例,对性能的影响最小:

https://github.com/plasma-umass/scalene

它可以在非常精细的水平上评测CPU、GPU和内存利用率。它还特别支持多线程/并行化的python代码。

PyVmMonitor是一种在Python中处理评测的新工具:http://www.pyvmmonitor.com/

它具有一些独特的功能,例如

将探查器附加到正在运行的(CPython)程序Yappi集成的按需分析不同机器上的配置文件多进程支持(多处理、django…)实时采样/CPU视图(带时间范围选择)通过cProfile/配置文件集成进行确定性配置分析现有PStats结果打开DOT文件编程API访问按方法或行对样本进行分组PyDev集成PyCharm集成

注意:它是商业的,但对开源是免费的。

@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

还有BLAM!

它使用点(与pycallgraph使用的相同),因此输出看起来类似。我觉得gprof2dot丢失的信息更少: