Python 系统中的孤立堆栈跟踪。\u当前\u帧()

Python 系统中的孤立堆栈跟踪。\u当前\u帧(),python,generator,stack-trace,introspection,Python,Generator,Stack Trace,Introspection,这里有一个深奥的纯Python问题 我正在使用sys.\u current\u frames()进行一些统计分析。i、 我有一个后台线程,每秒运行一次sys.\u current\u frames(),将结果转储到一个文本文件中,然后我有一些Python代码将回溯从最常见到最不常见进行排序 我看到的一个奇怪现象是这样的回溯: File "/opt/foo/bar.py", line 1437, in __iter__ yield key 这个yield是我写的一个生成器。奇怪的是,

这里有一个深奥的纯Python问题

我正在使用
sys.\u current\u frames()
进行一些统计分析。i、 我有一个后台线程,每秒运行一次
sys.\u current\u frames()
,将结果转储到一个文本文件中,然后我有一些Python代码将回溯从最常见到最不常见进行排序

我看到的一个奇怪现象是这样的回溯:

  File "/opt/foo/bar.py", line 1437, in __iter__
    yield key
这个
yield
是我写的一个生成器。奇怪的是,这个回溯只有一帧。这怎么可能?另一个回溯有很多帧,要么来自流程的顶层,要么来自帧的顶层。这个单帧堆栈跟踪的含义是什么


我的一个理论是,这是一个生成器的冻结状态,在它产生一个值之后,它等待再次调用
next
。但是我想我用一个单独的实验来反驳这个理论:我做了一个发电机,确保它被暂停,叫做
sys.\u current\u frames()
,我没有看到那种堆栈跟踪。
sys.\u current\u frames()
警告说

这对于调试死锁非常有用:此函数不需要死锁线程的合作,并且只要这些线程保持死锁,它们的调用堆栈就会被冻结。在调用代码检查帧时,为非死锁线程返回的帧可能与该线程的当前活动没有关系

sys.\u current\u frames()
在您无法保证感兴趣的线程暂停的任何情况下,都很容易出现争用情况


正如您所怀疑的,您正在看到一个暂停的生成器的堆栈跟踪。当生成器挂起时,其堆栈帧没有父帧。其
f_back
设置为空

sys.\u current\u frames()
检索当前正在运行的线程的堆栈帧,但是当您查看这些帧时,它们可能已经不再运行了。如果生成器在调用
sys.\u current\u frames()
和检查帧之间挂起,它将是这样的。如果它在其他地方恢复,您可能还会在调用堆栈顶部看到它,它看起来与实际调用
sys.\u current\u frames()
时完全不同


您的测试没有显示生成器框架,因为您在调用
sys.\u current\u frames()
之前而不是之后挂起了生成器。生成器的堆栈帧当时不是任何线程的活动帧。

A将有助于深入研究这个问题。有趣的理论,我将尝试创建一个实验来证明它。有趣的是,我只能在Python 3.5和Python 2.7中复制它,尽管它最初发生在Python 3.6上。下面是我复制它的代码:您可能需要多次运行它。谢谢你的回答!这引起了我的兴趣,所以我修改了@RamRachum的代码,在每次运行时生成“空”跟踪。我使用锁来几乎确保有一个从生成器中获取的帧,并且只有当它被挂起时才进行处理。