这是一个深奥的纯 Python 问题。
我正在使用 sys._current_frames()
做一些统计分析.即我有一个后台线程运行 sys._current_frames()
每秒一次,将结果转储到一个文本文件中,然后我得到了一些 Python 代码,将回溯从最常见到最不常见。
我见过的一种奇怪的现象是这样的回溯:
File "/opt/foo/bar.py", line 1437, in __iter__
yield key
此
yield
是我写的一个生成器。奇怪的是,这个回溯只有一个框架。这怎么可能?另一个回溯有很多框架,要么来自流程的顶层,要么来自框架的顶层。这个单帧堆栈跟踪是什么意思?我的一个理论是,这是一个生成器的卡住状态,在它产生一个值之后它正在等待
next
再次调用它。但我想我用一个单独的实验反驳了这个理论:我做了一个生成器,确保它被暂停,叫做 sys._current_frames()
我没有看到那种堆栈跟踪。
最佳答案
如 sys._current_frames()
documentation警告,
This is most useful for debugging deadlock: this function does not require the deadlocked threads’ cooperation, and such threads’ call stacks are frozen for as long as they remain deadlocked. The frame returned for a non-deadlocked thread may bear no relationship to that thread’s current activity by the time calling code examines the frame.
sys._current_frames()
在您无法保证感兴趣的线程暂停的任何情况下,自然容易出现竞争条件。正如您所怀疑的,您看到了一个暂停生成器的堆栈跟踪。当生成器挂起时,它的堆栈帧没有父帧。它的
f_back
设置为空。sys._current_frames()
检索当前正在运行的线程的堆栈帧,但是当您查看这些帧时,它们可能不再运行。如果生成器在您调用 sys._current_frames()
之间暂停当您检查框架时,这就是它的样子。您可能还会在调用堆栈顶部看到它,该堆栈看起来与您实际调用 sys._current_frames()
时完全不同。 ,如果它在其他地方恢复。您的测试没有显示生成器框架,因为您在调用
sys._current_frames()
之前暂停了生成器而不是之后。此时生成器的堆栈帧不是任何线程的事件帧。
关于python - sys._current_frames() 中的孤立堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61153469/