Python 使用decorator修补模块中的所有函数

Python 使用decorator修补模块中的所有函数,python,Python,我有一个包含很多函数的python模块,我想为所有函数应用一个装饰器。 有没有一种方法可以通过monkey patching对所有函数进行修补,从而对每个函数应用此装饰器,而无需在应用装饰器的行上进行复制粘贴 换言之,我想替换这个: @logging_decorator(args) func_1(): pass @logging_decorator(args) func_2(): pass @logging_decorator(args) func_3(): pass @lo

我有一个包含很多函数的python模块,我想为所有函数应用一个装饰器。 有没有一种方法可以通过monkey patching对所有函数进行修补,从而对每个函数应用此装饰器,而无需在应用装饰器的行上进行复制粘贴

换言之,我想替换这个:

@logging_decorator(args)
func_1():
  pass

@logging_decorator(args)
func_2():
  pass

@logging_decorator(args)
func_3():
  pass


@logging_decorator(args)
func_n():
  pass
为此:

patch_func():
  # get all functions of this module
  # apply @logging_decorator to all (or not all) of them

func_1():
  pass

func_2():
  pass

func_3():
  pass

func_n():
  pass

我真的不确定这是个好主意,毕竟

话虽如此,类似这样的东西应该可以工作,使用来找到模块的哪些成员可以被修饰,并使用来操作模块的内容

import inspect

def decorate_module(module, decorator):
    for name, member in inspect.getmembers(module):
        if inspect.getmodule(member) == module and callable(member):
            if member == decorate_module or member == decorator:
                continue
            module.__dict__[name] = decorator(member)
示例用法:

def simple_logger(f):
    def wrapper(*args, **kwargs):
        print("calling " + f.__name__)
        f(*args, **kwargs)
    return wrapper

def do_something():
    pass

decorate_module(sys.modules[__name__], simple_logger)
do_something()

我不会漂亮的。。。但是可以在定义之后使用dir()列出所有函数。那么,如果没有包装器函数,我想不出一种方法来修补它们

def patched(func):
    @logging_decorator
    def newfunc(*args, **kwargs):
        return func(*args, **kwargs)
    return newfunc

funcs=[f in dir() if not '__' in f]
for f in funcs:
    exec(f+'=patched(f)')

我不知道你会怎么做,但我认为你不应该。最好是直言不讳。查找/替换应该有助于解决必须为每个函数键入它的问题。不是在这一点上,而是当您
导入它时,您可以迭代模块公开的名称并从那里修补它们。您尝试过吗?“这看起来有点凌乱,”MarcelWilson说,“我理解,但这不是我唯一需要修补的地方。”。“没有一门课可以添加一个mixin或类似的东西来做得更像elegat的方式。”Paul我明白你的意思,并且承认这是一个聪明的主意。我担心,对于下一个代码维护者来说,结果会变得复杂/混乱。我明白了,有时候聪明并不总是更好。看起来和我需要的很相似!这里有没有办法把args传递给decorator?因为实际上
@logging\u decorator(args)
需要args来跟踪这些跟踪。带参数的decorator被实现为返回一个包装其参数的标准decorator-因此使用
decorator模块(module\u to\u wrap,logging\u decorator(args))
应该可以工作。我当前方法的局限性是,如果
logging\u decorator
存在于您试图包装的模块中,那么
decoration\u module
将尝试装饰它,这可能是不好的。(
decoration_module
尝试不修饰decorator,但由于使用参数进行修饰会动态生成新函数,因此这不起作用。)因此,实际上,我的日志修饰器存在于其他包中,因此我相信这不是问题。非常感谢。