2024-10-05 22:02:16 发布
网友
我有一个程序计算速度慢,我想调试算法。现在总是重新运行所有的东西是非常乏味的,我宁愿从程序中间重新启动。你能想出一些聪明的方法来达到这个目的吗?在
第一个模糊的想法是定义检查点(在这里我进行函数调用),在这里我用pickle和/或sqlite(sqlite能够检查中间数据)保存局部变量和大数据。稍后我可以尝试调用程序,告诉它在特定的检查点重新启动。不过,我不想为了这个目的在检查点之间分割所有代码块。在
有人知道如何解决这个调试问题吗?在
使你的程序更模块化。理想情况下,主代码块应该类似于
import config import my_numerics import post_processing my_numerics.configure(config.numerics) values = my_numerics.run() post_processing.run(values, config.post_processing)
你明白了。然后很容易生成一个“mock”numerics对象,该对象返回预先计算的数据,并将其传递给后处理。在
编辑:我还是不明白。以下是您的问题的正确伪代码吗?在
也就是说,你想在数字运行的中途中断(不是在末尾),比如在第三个循环的开始,而不必重新运行前两个?在
如果是这样,即使循环不包含太多代码,也应模块化设计:
input_data = np.load(some_stuff) stage_one = do_thing_one(input_data) stage_two = do_thing_two(stage_one) stage_three = do_thing_three(stage_two)
第一种方法是通过隐式接口(即局部变量字典)在不同的阶段之间传输数据。这是不好的,因为您还没有定义要使用哪些变量,因此您不能为了测试/调试目的而模拟它们。第二种方法定义函数之间的(基本)接口。现在您不再关心do_thing_one做什么了,只要它接受一些输入数据并返回一些输出数据。{cd2>这意味着你可以调试
do_thing_one
stage_two = np.load(intermediate_stuff) stage_three = do_thing_three(stage_two)
只要stage_two中的数据格式正确,它来自何处都无关紧要。在
stage_two
一个google搜索让我找到了CryoPID,如果你是在基于linux的系统上开发的话,这可能就可以了。它声称能够挂起一个进程并将其保存到一个文件中,然后再重新启动它,即使是在另一台计算机上。不过我还没有测试过。在
单元测试
这就是为什么存在单元测试。尝试使用小的“示例数据”pyunit,或者使用非常简单的函数doctest。在
pyunit
doctest
小型测试程序
如果出于某种原因你真的需要交互性,我通常编写一个交互式的小程序,作为一个有效的单元测试。在
def _interactiveTest(): ... import code code.interact(local=locals()) if __name__=='__main__': _interactiveTest()
如果只测试某个特定的部分,通常可以忽略加载主程序的大块;根据需要调整体系结构,以避免初始化程序中不需要的部分。这就是为什么人们会说“让你的程序更模块化”,这就是模块化的意思:程序的小部分独立,让你重用它们或者(在这种情况下)单独加载它们。在
在程序中调用解释器
您还可以在程序中的任何时候,下拉到一个解释器中,并传入局部变量(如上所示)。这有点像“穷人的调试器”,但我觉得它足够有效。=)
单片算法
去过那里,做了。有时候,你的工作流程无法进一步模块化,事情开始变得难以处理。在
你建立检查点的直觉是非常好的,我也使用这个直觉:如果你在一个解释器环境中工作,或者嵌入一个解释器,你就不必像重新运行脚本那样频繁地处理这个问题。序列化数据可以工作,但它会带来从磁盘读写的大量开销;您希望数据集保留在内存中。然后您可以做类似test1 = algorithm(data), test2 = algorithm(data)(这假设您的算法不是一个就地算法;如果是,请在每次测试之前使用“写入时复制”或复制数据结构)。在
test1 = algorithm(data), test2 = algorithm(data)
如果您在尝试了以上所有方法后仍有问题,那么您可能是:
作为最后的手段,您可以对代码进行概要分析以找出瓶颈。在
其他
可能有强大的python调试器。我想日蚀有一个。在
另外,我个人会避免使用reload <modulename>,我发现这会让人头疼,而不是解决问题。在
reload <modulename>
使你的程序更模块化。理想情况下,主代码块应该类似于
你明白了。然后很容易生成一个“mock”numerics对象,该对象返回预先计算的数据,并将其传递给后处理。在
编辑:我还是不明白。以下是您的问题的正确伪代码吗?在
^{pr2}$也就是说,你想在数字运行的中途中断(不是在末尾),比如在第三个循环的开始,而不必重新运行前两个?在
如果是这样,即使循环不包含太多代码,也应模块化设计:
第一种方法是通过隐式接口(即局部变量字典)在不同的阶段之间传输数据。这是不好的,因为您还没有定义要使用哪些变量,因此您不能为了测试/调试目的而模拟它们。第二种方法定义函数之间的(基本)接口。现在您不再关心
do_thing_one
做什么了,只要它接受一些输入数据并返回一些输出数据。{cd2>这意味着你可以调试只要
stage_two
中的数据格式正确,它来自何处都无关紧要。在一个google搜索让我找到了CryoPID,如果你是在基于linux的系统上开发的话,这可能就可以了。它声称能够挂起一个进程并将其保存到一个文件中,然后再重新启动它,即使是在另一台计算机上。不过我还没有测试过。在
单元测试
这就是为什么存在单元测试。尝试使用小的“示例数据”
pyunit
,或者使用非常简单的函数doctest
。在小型测试程序
如果出于某种原因你真的需要交互性,我通常编写一个交互式的小程序,作为一个有效的单元测试。在
如果只测试某个特定的部分,通常可以忽略加载主程序的大块;根据需要调整体系结构,以避免初始化程序中不需要的部分。这就是为什么人们会说“让你的程序更模块化”,这就是模块化的意思:程序的小部分独立,让你重用它们或者(在这种情况下)单独加载它们。在
在程序中调用解释器
您还可以在程序中的任何时候,下拉到一个解释器中,并传入局部变量(如上所示)。这有点像“穷人的调试器”,但我觉得它足够有效。=)
单片算法
去过那里,做了。有时候,你的工作流程无法进一步模块化,事情开始变得难以处理。在
你建立检查点的直觉是非常好的,我也使用这个直觉:如果你在一个解释器环境中工作,或者嵌入一个解释器,你就不必像重新运行脚本那样频繁地处理这个问题。序列化数据可以工作,但它会带来从磁盘读写的大量开销;您希望数据集保留在内存中。然后您可以做类似
test1 = algorithm(data), test2 = algorithm(data)
(这假设您的算法不是一个就地算法;如果是,请在每次测试之前使用“写入时复制”或复制数据结构)。在如果您在尝试了以上所有方法后仍有问题,那么您可能是:
作为最后的手段,您可以对代码进行概要分析以找出瓶颈。在
其他
可能有强大的python调试器。我想日蚀有一个。在
另外,我个人会避免使用
reload <modulename>
,我发现这会让人头疼,而不是解决问题。在相关问题 更多 >
编程相关推荐