адрес стека вызовов трассировки python - PullRequest
0 голосов
/ 18 апреля 2020

Для отслеживания полной истории звонков, то есть последовательности 'F_BACK'

Вот мой код:

import sys
def trace_calls(frame, event, arg):
    if event != 'call':
        return
    co = frame.f_code
    func_name = co.co_name
    if func_name == 'write':
        return

    caller = frame.f_back

    print ('TRACE\t%s\tF_BACK\t%s' % (caller, frame))
    return

sys.settrace(trace_calls)

def a():                                                                                                                                                                                                                                                                       
    print("i am A")


def b():
    print("i am B")
    a()                                                                                                                                                                                                                                           

if __name__ == '__main__':
    sys.settrace(trace_calls)
    a()
    b()

Вывод:

>TRACE   <frame at 0x7f3c14a80650, file '/tmp/test1.py', line 40, code <module>> F_BACK  <frame at 0x5587b0ee4050, file '/tmp/test1.py', line 21, code a>
>i am A
>TRACE   <frame at 0x7f3c14a80650, file '/tmp/test1.py', line 41, code <module>> F_BACK  <frame at 0x5587b0ec3da0, file '/tmp/test1.py', line 24, code b>
>i am B
>TRACE   <frame at 0x5587b0ec3da0, file '/tmp/test1.py', line 26, code b>        F_BACK  <frame at 0x5587b0ee4050, file '/tmp/test1.py', line 21, code a>
>i am A
  1. Правильно ли я понимаю, что ID - это адрес памяти кадра стека?
  2. если (1.), Почему я получаю один и тот же адрес из 2 вызовов функции a ()?
  3. Во многих тестах идентификатор, скорее всего, будет входом в функцию, поэтому он исправлен. Как тогда я получу адрес / идентификатор фрейма?

ОБНОВЛЕНИЕ: первый вызов a () был помещен в конец стека, потому что это вызов верхнего уровня; второй a () был вызван внутри b (), должен быть на один уровень глубже в стеке, но часть идентификатора двух вызовов одинакова.

Спасибо.

1 Ответ

0 голосов
/ 18 апреля 2020
Функции

Python не используют стек C для своих данных. Когда вы вызываете функцию, python создает объект фрейма выполнения для хранения локальных данных для этого одного вызова. В вашем примере a() создает объект фрейма при вызове, и это фрейм, который содержит первый вызов print. a возвращает, кадр освобождается и возвращается в кучу. Следующий вызов b() также создает фреймовый объект, и он просто оказывается свободным в строке выше. Его печать имеет новый кадр, который используется для повторного использования памяти ранее освобожденного кадра.

...