如何调试永不停止运行的代码?

cam*_*mil 3 python python-2.7

我有一个庞大的代码库,现在执行的东西太长了.我不知道是什么.

代码永远不会引发异常,它似乎只是继续处理某些东西.

我想做的是在一些函数周围放置计时器来测试哪一个是罪魁祸首.但我不确定这是否是正确的方法,或者如何做到这一点.

我不能轻易地在代码周围的点处引发异常,因为有各种循环调用相同的函数,这可能有时只需要太长时间.

什么是最好的策略?

Dav*_*son 9

一种解决方案是使用cProfile内置于Python中的函数来说明代码花费最多时间的函数.重要的是,即使您使用a停止代码 ,此分析仍然有效KeyboardInterrupt.因此,您可以启动代码运行和分析,在一两分钟后停止它,然后查看它花费时间的位置.

运行这些额外的代码-m-o参数:

python -m cProfile -o profile.txt myscript.py
Run Code Online (Sandbox Code Playgroud)

然后一旦程序运行完毕,运行以下代码(例如,从另一个脚本):

import pstats
p = pstats.Stats('profile.txt')
p.strip_dirs().sort_stats("time").print_stats()
Run Code Online (Sandbox Code Playgroud)

这将打印按照您在其中花费的总时间排序的函数列表.

这是使用分析来调试无限循环的演示.假设myscript.py有以下代码.

def f():
    while True:
        g(100000)

def g(n):
    x = []
    for i in range(n):
        x.append(n)

f()
Run Code Online (Sandbox Code Playgroud)

当然,这会导致无限循环运行很多次.所以我运行上面的profiling命令,但是我在大约30-40秒后停止它(甚至可以短得多).其简介将打印为:

Wed Jan 30 10:58:50 2013    profile.txt

         115414854 function calls in 37.705 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1155   25.787    0.022   37.020    0.032 test3.py:5(g)
115412541   10.060    0.000   10.060    0.000 {method 'append' of 'list' objects}
     1155    1.173    0.001    1.173    0.001 {range}
        1    0.685    0.685   37.705   37.705 test3.py:1(f)
        1    0.000    0.000   37.705   37.705 test3.py:1(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
Run Code Online (Sandbox Code Playgroud)

请注意,我们的无限循环函数g就函数所花费的时间而言位于列表的顶部.

注意:仅仅因为代码在一个函数中花费所有时间并不意味着循环直接围绕该函数 - 它可以被一个由无限循环中的函数(etc)调用的函数调用(append因为在里面调用它,所以在列表顶部附近的通知g).另一种方法是根据每个函数的累计时间对它们进行排序.sort_stats("cum").这两种方法的结合,以及一些小的侦探工作(查看代码和添加调试消息)应该能够找出罪魁祸首.