Python Generators и yield: как узнать, в какой строке находится программа - PullRequest
3 голосов
/ 16 сентября 2011

Предположим, у вас есть простой генератор на 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 (), которая была выполнена до того, как произошла клавиатурная ошибка?

Ответы [ 4 ]

4 голосов
/ 16 сентября 2011

Вы можете использовать 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, конечно, будет Нет)

Или очень явно, используя подробное указание:

def f():

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


for message in f():
    try:
        time.sleep(2)
    except KeyboardInterrupt:
        print(message)
2 голосов
/ 16 сентября 2011

Если вы хотите узнать номер строки для целей отладки, тогда в CPython вы можете использовать h.gi_frame.f_lineno.Эта строка будет выполнена следующим и будет проиндексирована на 1.Я не уверен, работает ли это на реализациях Python, отличных от 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.

Если вы не хотите знать это для целей отладки, тогда Решение Remi enumerate далекоочиститель.

1 голос
/ 16 сентября 2011
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().

1 голос
/ 16 сентября 2011

Почему бы вам не вернуть i из f () и не использовать это?

val = h.next()
...