Вызов порядка функций [дубликат]

Имейте в виду, что независимо от сценария причина всегда одинакова в .NET:

Вы пытаетесь использовать ссылочную переменную, значение которой Nothing / null. Если для ссылочной переменной значение Nothing / null, это означает, что на самом деле оно не содержит ссылку на экземпляр любого объекта, который существует в куче.

Вы либо никогда не присваивали какую-либо переменную, никогда не создавали экземпляр значения, присвоенного переменной, или вы вручную устанавливали переменную, равную Nothing / null, или вы вызывали функцию, которая установите для этой переменной значение Nothing / null.

48
задан James 29 November 2011 в 19:56
поделиться

5 ответов

Вы можете сделать это с помощью функции трассировки (реквизиты для Spacedman для улучшения исходной версии этого для отслеживания возвратов и использования некоторого приятного отступа):

def tracefunc(frame, event, arg, indent=[0]):
      if event == "call":
          indent[0] += 2
          print "-" * indent[0] + "> call function", frame.f_code.co_name
      elif event == "return":
          print "<" + "-" * indent[0], "exit function", frame.f_code.co_name
          indent[0] -= 2
      return tracefunc

import sys
sys.settrace(tracefunc)

main()   # or whatever kicks off your script

Обратите внимание, что объект кода функции обычно имеет то же имя, что и связанная функция, но не всегда, так как функции могут создаваться динамически. К сожалению, Python не отслеживает объекты функции в стеке (я иногда фантазировал о том, чтобы указать для этого патч). Тем не менее, это в большинстве случаев «достаточно хорошо».

Если это становится проблемой, вы можете извлечь «реальное» имя функции из исходного кода: Python отслеживает имя файла и номер строки - или попросите сборщика мусора выяснить, какой объект функции ссылается на объект кода. Может быть более одной функции, разделяющей объект кода, но любое из их имен может быть достаточно хорошим.

Возвращаясь к этому четыре года спустя, мне следует сказать, что в Python 2.6 и позже вы можете получить более высокую производительность, используя sys.setprofile(), а не sys.settrace(). Можно использовать ту же самую функцию трассировки; это просто, что функция профиля вызывается только при вводе или выходе функции, поэтому функция внутри функции выполняется на полной скорости.

78
ответ дан martineau 26 August 2018 в 04:25
поделиться
import traceback
def foo():
    traceback.print_stack()
def bar():
    foo()
def car():
    bar():

car()
File "<string>", line 1, in <module>
File "C:\Python27\lib\idlelib\run.py", line 97, in main
  ret = method(*args, **kwargs)
File "C:\Python27\lib\idlelib\run.py", line 298, in runcode
    exec code in self.locals
File "<pyshell#494>", line 1, in <module>
File "<pyshell#493>", line 2, in car
File "<pyshell#490>", line 2, in bar
File "<pyshell#486>", line 2, in foo

traceback

4
ответ дан Abhijit 26 August 2018 в 04:25
поделиться

Еще один хороший инструмент, который нужно знать, это модуль trace :

$ cat foo.py
def foo():
   bar()

def bar():
   print "in bar!"

foo()

$ python -m trace --listfuncs foo.py
in bar!

functions called:
filename: /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/trace.py, modulename: trace, funcname: _unsettrace
filename: foo.py, modulename: foo, funcname: 
filename: foo.py, modulename: foo, funcname: bar
filename: foo.py, modulename: foo, funcname: foo

$python -m trace --trace foo.py
 --- modulename: foo, funcname: 
foo.py(1): def foo():
foo.py(4): def bar():
foo.py(7): foo()
 --- modulename: foo, funcname: foo
foo.py(2):    bar()
 --- modulename: foo, funcname: bar
foo.py(5):    print "in bar!"
in bar!
 --- modulename: trace, funcname: _unsettrace
trace.py(80):         sys.settrace(None)

6
ответ дан David Wolever 26 August 2018 в 04:25
поделиться

Вы можете использовать settrace, как описано здесь: Трассировка кода python . Используйте версию в конце страницы. Я вставляю код этой страницы в свой код, чтобы точно увидеть, какие строки выполняются при работе моего кода. Вы также можете фильтровать так, чтобы вы видели только имена названных функций.

2
ответ дан jeorgen 26 August 2018 в 04:25
поделиться

Есть несколько вариантов. Если отладчика недостаточно, вы можете установить функцию трассировки с помощью sys.settrace() . Эта функция будет по существу вызываться в каждой строке исполняемого кода Python, но легко идентифицировать вызовы функций - см. Связанную документацию.

Вас также может заинтересовать trace , хотя он не делает именно то, что вы просили. Обязательно загляните в опцию --trackcalls.

7
ответ дан lesmana 26 August 2018 в 04:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: