gpt4 book ai didi

python - python中的面向方面的技术?

转载 作者:太空狗 更新时间:2023-10-30 02:50:37 24 4
gpt4 key购买 nike

所以我在 Python 中遇到了一个有趣的问题,它可以通过面向方面的技术来解决。情况是这样的:

  1. 我有一堆模块,每个模块都有一堆功能。
  2. 我有一个可执行文件调用这些模块中的一些函数集。
  3. 当可执行文件调用其中一个函数时,我想要生成一个包含函数调用详细信息(名称和参数)的日志语句
  4. 当其中一个模块调用其他模块的函数时,我不希望生成任何日志语句。

有没有什么方便的方法可以在 Python 中执行此操作,而无需在每个模块的函数中添加日志记录语句?

最佳答案

可以使用装饰器修改可执行文件中函数的行为:

#!/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')

注意上面的trace

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,因为 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

关于python - python中的面向方面的技术?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1723849/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com