определить, какой вызов функции выполняется в данный момент - PullRequest
1 голос
/ 19 марта 2019

При наличии нескольких вызовов одной и той же функции на одной и той же линии. Возможно ли в целях устранения неполадок использовать трассировку или библиотеку sys, чтобы определить, какая из них в данный момент выполняется?

Редактировать: Пожалуйста, не предоставляйте решение проблемы. Я знаю все, что мне нужно знать о том, как обойти эту проблему. Я хотел бы знать, есть ли способ найти более точную информацию о состоянии анализа / выполнения, чем просто номер строки инструкции вызова.

Давайте рассмотрим этот пример:

#!/usr/bin/python3
# coding: UTF-8


def fn(var):
    import traceback
    print(repr(traceback.extract_stack()[-2]))
    return var+1

a = b = 4
print(fn(a)+fn(b))

Запустив это в простое, напишу:

 RESTART: /.../python/framesummary.py 
<FrameSummary file /.../python/framesummary.py, line 11 in <module>>
<FrameSummary file /.../python/framesummary.py, line 11 in <module>>
10

Есть ли способ узнать внутри функции fn, выполняет ли она в данный момент fn(a) или fn(b)?


Редактировать2:

Я добавил случай, который показывает, что порядок вызова не может быть использован

#!/usr/bin/python3
# coding: UTF-8

def fn(var):
    import traceback
    stack = traceback.extract_stack()
    print(repr(stack[-2]))
    print("code = '"+stack[-2][-1]+"'")

    import sys
    calling_frame = sys._getframe(1)
    print("lasti =", calling_frame.f_lasti)
    print()

    return var+1

a = b = 4
print("case = sum", fn(a)+fn(b), "\n")
for boole in False, True:
    print("case =", boole, fn(a) if boole else fn(b), "\n")

напечатает:

 RESTART: /.../python/framesummary cleaned.py 
<FrameSummary file /.../python/framesummary cleaned.py, line 18 in <module>>
code = 'print("case = sum", fn(a)+fn(b), "\n")'
lasti = 34

<FrameSummary file /.../python/framesummary cleaned.py, line 18 in <module>>
code = 'print("case = sum", fn(a)+fn(b), "\n")'
lasti = 43

case = sum 10 

<FrameSummary file /.../python/framesummary cleaned.py, line 20 in <module>>
code = 'print("case =", boole, fn(a) if boole else fn(b), "\n")'
lasti = 100

case = False 5 

<FrameSummary file /.../python/framesummary cleaned.py, line 20 in <module>>
code = 'print("case =", boole, fn(a) if boole else fn(b), "\n")'
lasti = 88

case = True 5 

было бы неплохо иметь указание на первый символ вызова или способ перекомпиляции кода, чтобы получить значения lasti, соответствующие каждому вызову.

Очевидно, что анализ результата показывает, что значения lasti коррелируют с положением, но до сих пор я не нашел способа узнать это соотношение до выполнения программы:

lasti =  34 => (line, column) = (18, 33) (or pos=29 in unindented string⁽¹⁾)
lasti =  43 => (line, column) = (18, 39) (or pos=35 in unindented string⁽¹⁾)
lasti =  88 => (line, column) = (20, 40) (or pos=32 in unindented string⁽¹⁾)
lasti = 100 => (line, column) = (20, 60) (or pos=52 in unindented string⁽¹⁾)

(1) как указано в стеке [-2] [- 1]

Ответы [ 2 ]

0 голосов
/ 19 марта 2019

Я думаю, что вам лучше всего научиться использовать pdb . Хотя вы могли бы изменить код, чтобы дать вам какой-то ограниченный самоанализ в работающий код. Будет проще и в конечном итоге более ценно получить работающий отладчик, который позволит вам наблюдать за состоянием кода во время его оценки.

попробуй pdb

def fn(var):
    import pdb; pdb.set_trace()
    return var+1

a = b = 4
print(fn(a)+fn(b)

это откроет отладчик python и позволит вам делать такие вещи, как использование w, которое обозначает, где и в pdb печатает трассировку стека. Или l, который показывает источник в текущей строке выполнения и т. Д.

Это будет выглядеть примерно так

owen@lettuce:~ python temp.py
> /home/owen/temp.py(3)fn()
-> return var+1
(Pdb) w
  /home/owen/temp.py(6)<module>()
-> print(fn(a)+fn(b))
> /home/owen/temp.py(3)fn()
-> return var+1
(Pdb) l
  1     def fn(var):
  2         import pdb; pdb.set_trace()
  3  ->     return var+1
  4
  5     a = b = 4
  6     print(fn(a)+fn(b))
[EOF]
(Pdb)

Удачи. Надеюсь, это поможет.

0 голосов
/ 19 марта 2019

В качестве дополнительного параметра вы можете отправить уникальный и случайный идентификатор и добавить его в журналы.

Идентификатор поможет вам вернуться к источнику.

a = b = 4
id1 = some random no.
id2 = some random no.
print(fn(a, id1)+fn(b, id2))
...