Python 生成器和yield:如何知道程序位于哪一行

发布于 2024-12-04 14:00:24 字数 538 浏览 1 评论 0原文

假设你有一个简单的 Python 生成器,如下所示:

更新:

def f(self):        
    customFunction_1(argList_1)
    yield
    customFunction_2(argList_2)
    yield
    customFunction_3(argList_3)
    yield
    ...

我在另一个脚本中调用 f(),例如:

    h=f()
    while True:
        try:
            h.next()
            sleep(2)
        except KeyboardInterrupt:
                              ##[TODO] tell the last line in f() that was executed

有没有办法可以执行上面的 [TODO] 部分?也就是说知道 f() 中在键盘中断发生之前执行的最后一行?

Suppose you have a simple generator in Python like this :

Update :

def f(self):        
    customFunction_1(argList_1)
    yield
    customFunction_2(argList_2)
    yield
    customFunction_3(argList_3)
    yield
    ...

I call f() in another script like :

    h=f()
    while True:
        try:
            h.next()
            sleep(2)
        except KeyboardInterrupt:
                              ##[TODO] tell the last line in f() that was executed

Is there a way that I can do the [TODO] section above? that is knowing the last line in f() that was executed before keyboardInterrupt occurred ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鸢与 2024-12-11 14:00:24

您可以使用 enumerate() 来计数:(

def f():

    ...
    yield
    ...
    yield
    ... 


for step, value in enumerate(f()):
    try:
        time.sleep(2)
    except KeyboardInterrupt:
        print(step) # step holds the number of the last executed function

因为在您的示例中 yield 不会产生值,value 当然将为 None)

或者非常明确地使用详细指示:

def f():

    ...
    yield 'first function finished'
    ...
    yield 'almost done'
    ... 


for message in f():
    try:
        time.sleep(2)
    except KeyboardInterrupt:
        print(message)

You can use enumerate() to count:

def f():

    ...
    yield
    ...
    yield
    ... 


for step, value in enumerate(f()):
    try:
        time.sleep(2)
    except KeyboardInterrupt:
        print(step) # step holds the number of the last executed function

(because in your example yield does not yield a value, value will of course be None)

Or very explicit using a verbose indication:

def f():

    ...
    yield 'first function finished'
    ...
    yield 'almost done'
    ... 


for message in f():
    try:
        time.sleep(2)
    except KeyboardInterrupt:
        print(message)
狠疯拽 2024-12-11 14:00:24

如果您想知道行号以进行调试,那么在 CPython 中您可以使用 h.gi_frame.f_lineno。这是接下来要执行的行,索引为 1。我不确定这是否适用于 CPython 以外的 Python 实现。

h=f()
while True:
    try:
        h.next()
        sleep(2)
    except KeyboardInterrupt:
        print h.gi_frame.f_lineno - 1 # f_lineno is the line to be executed next.

如果您不想出于调试目的了解这一点,那么 Remi 的 enumerate 解决方案 更加简洁。

If you want to know the line number for debugging purposes then in CPython you can use h.gi_frame.f_lineno. This is the line which will be executed next and is 1-indexed. I'm not sure if this works on Python implementations other than CPython.

h=f()
while True:
    try:
        h.next()
        sleep(2)
    except KeyboardInterrupt:
        print h.gi_frame.f_lineno - 1 # f_lineno is the line to be executed next.

If you don't want to know this for debugging purposes then Remi's enumerate solution is far cleaner.

灼疼热情 2024-12-11 14:00:24

为什么不从 f() 中产生 i 并使用它?

val = h.next()

Why don't you yield i from f() and use that ?

val = h.next()
疯了 2024-12-11 14:00:24
def f(self):        
    sleep(10)
    yield
    sleep(10)
    yield
    sleep(10)
    yield


h=f()
while True:
    try:
        h.next()
    except KeyboardInterrupt:
        stack_trace = sys.exc_info()[2]    # first traceback points into this function where the exception was caught
        stack_trace = stack_trace.tb_next  # now we are pointing to where it happened (in this case)
        line_no = stack_trace.tb_lineno    # and here's the line number
        del stack_trace                    # get rid of circular references

我将对 sleep() 的调用移至 f 中,因为只有当异常发生在 f() 内部时,这才有效。

def f(self):        
    sleep(10)
    yield
    sleep(10)
    yield
    sleep(10)
    yield


h=f()
while True:
    try:
        h.next()
    except KeyboardInterrupt:
        stack_trace = sys.exc_info()[2]    # first traceback points into this function where the exception was caught
        stack_trace = stack_trace.tb_next  # now we are pointing to where it happened (in this case)
        line_no = stack_trace.tb_lineno    # and here's the line number
        del stack_trace                    # get rid of circular references

I moved the call to sleep() into f as this only works if the exception happens inside f().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文