我该如何判断我的Python脚本在哪儿卡住了?

93 投票
14 回答
104738 浏览
提问于 2025-04-16 02:33

我正在调试我的Python程序,遇到了一个问题,导致程序卡住,感觉像是进入了无限循环。之前我也遇到过无限循环的问题,当程序卡住时,我可以强制结束它,然后Python会给我一个有用的错误提示,告诉我在我发送结束命令时程序是在哪里停止的。但是现在,当程序卡住,我按下Ctrl+C时,它并没有停止,而是继续运行。有没有什么工具可以帮助我找到卡住的原因?我对性能分析还很陌生,但我知道性能分析器通常只能提供关于成功完成的程序的信息。那我能不能用性能分析器来调试这种卡住的情况呢?

14 个回答

25

哇!已经有5个回答了,但没有人提到最简单最明显的方法:

  1. 试着找一个能重复出现的问题案例,看看是什么导致程序卡住的。
  2. 在你的代码里加一些日志记录。这可以很简单,比如在重要的地方加上 print "**010"print "**020" 这样的打印语句。
  3. 运行代码,看看程序在哪个地方卡住了。如果不明白为什么卡住了?那就再加更多的日志记录。(比如如果在 **020 和 **030 之间卡住了,就可以加 **023、**025、**027 等等。)
  4. 回到第3步。
32

我写了一个模块,可以打印出在某个地方卡住超过10秒的线程。

你可以在这里找到这个模块:hanging_threads.py

运行方法:

python -m pip install hanging_threads

把这个添加到你的代码里:

from hanging_threads import start_monitoring
start_monitoring(seconds_frozen=10, test_interval=100)

下面是一个示例输出:

--------------------    Thread 5588     --------------------
  File "C:\python33\lib\threading.py", line 844, in _exitfunc
        t.join()
  File "C:\python33\lib\threading.py", line 743, in join
        self._block.wait()
  File "C:\python33\lib\threading.py", line 184, in wait
        waiter.acquire()

这个问题发生在主线程退出时,如果你忘记把其他线程设置为守护线程,就会出现这个情况。

140

假设你正在这样运行你的程序:

python YOURSCRIPT.py

试着这样运行你的程序:

python -m trace --trace YOURSCRIPT.py

在屏幕上会打印出很多内容,耐心点。如果你的程序有个无限循环,它会一直运行下去(这就是“停机问题”)。如果程序卡住了,通常是因为在输入输出方面出了问题,或者是出现了死锁。

撰写回答