gpt4 book ai didi

python - 如何在 Python 中获取生成器执行的最后一行

转载 作者:行者123 更新时间:2023-12-01 02:00:31 25 4
gpt4 key购买 nike

我正在尝试获取 Python 中生成器执行的最后一行的数量。我找到了在几种情况下获得它的方法:

  • 发电机因产量而暂停,
  • 生成器因异常而失败(不是 StopIteration),
  • 通过显式引发StopIteration返回的生成器。

但是我想询问如何在生成器执行 return 语句或刚刚到达最后一行后自动引发 StopIteration 的情况下获取行号相应的功能。

下面列出了我使用的简化代码示例。

from sys import exc_info

def gen1():
print("1.1")
yield
print("1.2")
raise StopIteration()

def gen2():
print("2.1")
yield
print("2.2")
return

def gen3():
print("3.1")
yield
print("3.2")
raise RuntimeError()

for gen in [ g for n, g in globals().items() if n.startswith("gen") ]:
g = gen() # launch the generator
while True:
try:
next(g)
except StopIteration: # generator normally returned
tb = exc_info()[2].tb_next
if tb is None:
print("How to get last line?")
else:
print("last line: %s" % tb.tb_frame.f_lineno)
break
except BaseException: # generator failure
tb = exc_info()[2].tb_next
print("last line: %s" % tb.tb_frame.f_lineno)
break
else:
print("last line: %s" % g.gi_frame.f_lineno)

执行此代码返回:

3.1
last line: 17
3.2
last line: 19
2.1
last line: 11
2.2
How to get last line?
1.1
last line: 5
1.2
last line: 7

最佳答案

您想要的信息位于框架对象中。

但是框架对象已经被垃圾回收了。 g.gi_frame 中对它的引用设置为None当函数返回时。

回溯不会帮助你,因为回溯来自函数返回后解释器内部的机器,所以它无处可获取它(并且你已经看到它甚至没有尝试)。

<小时/>

但是如果您可以更改代码以获取对 gi_frame 的引用在生成器运行时保存对象并在生成器完成后保留它,您将保持该对象以及所有其他相关垃圾的事件。

这意味着f_lineno可能是有效的,正如您在最后一个从未发生过的情况中所使用的那样。不知道有没有办法查到f_lineno什么时候是并且没有意义,但是如果您深入研究其源代码,回溯生成代码可能会知道这一点。

如果没有,f_lasti肯定是 RETURN_VALUE 的字节码偏移量作品。 Python 当然不能保证它不会对 lasti 做任何奇怪的事情。在发布框架之前,但它还没有出现在任何版本中,而且很难看出将来有什么理由这样做。因此,使用 f_code.co_lnotab 中的信息应该始终是正确的。生成 f_lasti 的行号。请参阅dis模块寻求帮助。 (如果您的 Python 足够新,它会公开 findlinestarts 来为您完成此操作;如果没有,请阅读模块的源代码。或者从解释器源代码的 Objects 目录中的文档编写您自己的 lnotab 解析器,如果你想要一些真正的乐趣。)

关于python - 如何在 Python 中获取生成器执行的最后一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49710035/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com