Изменить поведение функций в исполняемом файле можно с помощью декоратора:
#!/usr/bin/env python
from module1 import foo
from module2 import bar
def trace(f):
def tracewrapper(*arg, **kw):
arg_str=','.join(['%r'%a for a in arg]+['%s=%s'%(key,kw[key]) for key in kw])
print "%s(%s)" % (f.__name__, arg_str)
return f(*arg, **kw)
return tracewrapper
verbose_functions=[foo,bar] # add whatever functions you want logged here
for func in verbose_functions:
globals()[func.func_name]=trace(func)
Поскольку вы изменяете только определение функций в пространстве имен исполняемого файла, функции модулей остаются без изменений. Когда функция одного модуля вызывает функцию другого модуля, она не декорируется трассировкой, и оператор журнала не генерируется.
Если вы хотите регистрировать вызовы функций только тогда, когда они приходят непосредственно из main (),
тогда вы могли бы использовать декоратор следов, как это:
import traceback
def trace(f,filename,funcname):
def tracewrapper(*arg, **kw):
stacks=traceback.extract_stack()
(s_filename,s_lineno,s_funcname,s_text)=stacks[-2]
# Alternatively, you can search the entire call stack
# for (s_filename,s_lineno,s_funcname,s_text) in stacks:
if s_filename.endswith(filename) and s_funcname==funcname:
arg_str=','.join(['%r'%a for a in arg]+
['%s=%s'%(key,kw[key]) for key in kw])
print "%s(%s)" % (f.__name__, arg_str)
return f(*arg, **kw)
return tracewrapper
verbose_functions=[foo,bar] # add whatever functions you want logged here
for func in verbose_functions:
# You can pass the module's filename and the function name here
globals()[func.func_name]=trace(func,'test.py','main')
Обратите внимание, что с приведенным выше следом
def baz():
foo(3,4)
def main():
foo(1,2,'Hi')
bar(x=3)
baz()
будет регистрировать вызовы foo(1,2,'Hi')
и bar(x=3)
, но не foo(3,4)
, так как это
звонок не приходит напрямую с основного. Однако это косвенно происходит от main, поскольку main вызывает baz
. Если вы хотите записать вызов foo(3,4)
, то вы хотите
цикл по всему стеку:
import traceback
def trace(f,filename,funcname):
def tracewrapper(*arg, **kw):
stacks=traceback.extract_stack()
for (s_filename,s_lineno,s_funcname,s_text) in stacks:
if s_filename.endswith(filename) and s_funcname==funcname:
arg_str=','.join(['%r'%a for a in arg]+
['%s=%s'%(key,kw[key]) for key in kw])
print "%s(%s)" % (f.__name__, arg_str)
return f(*arg, **kw)
return tracewrapper