解决使用@wraps装饰器,但是仍然未消除装饰器产生的副作用问题

Posted 七月的小尾巴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决使用@wraps装饰器,但是仍然未消除装饰器产生的副作用问题相关的知识,希望对你有一定的参考价值。

前言

今天在封装自动化框架中的日志装饰器的时候,遇到一个问题,我想要打印引用装饰器中的函数名称,大家都知道,如果没有用 @wraps 装饰器,会打印出装饰器自身的函数名,那么我们就需要使用了 @wraps 去消除封装装饰器产生的副作用,打印引用装饰器的函数名称,但是我使用了@wraps 之后,发现并没有生效。

下面是我封装的日志装饰器的代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time   : 2021/11/30 23:25
# @Author : 余少琪
import os
from functools import wraps
from tools.logControl import INFO

def logDecorator(switch):
    """
    封装日志装饰器, 打印请求信息
    :param switch: 定义日志开关
    :return:
    """
    # 判断参数类型是否是 int 类型
    if isinstance(switch, bool):
        def decorator(func):
            @wraps(func)
            def swapper(*args, **kwargs):
                # 判断日志为开启状态,才打印日志
                if switch:
                    res = func(*args, **kwargs)
                    if res is not None:
                        INFO.logger.info(
                            f"\\n=================================================================================\\n"
                            f"测试标题: res[2]['detail']\\n"
                            f"请求方式: res[2]['method']\\n"
                            f"请求头:   res[2]['headers']\\n"
                            f"请求路径: res[2]['url']\\n"
                            f"请求内容: res[2]['data']\\n"
                            f"接口响应内容: res[0]\\n"
                            f"数据库断言数据: res[1]\\n"
                            f"文件名称: func.__name__\\n"
                            "================================================================================="

                        )
                    return res
            return swapper

        return decorator
    else:
        raise TypeError("日志开关只能为 Ture 或者 False")

下面我们来运行一下代码,查看一下结果,可以看到我在装饰器文件中封装了一个test函数,调用这个装饰器的时候,是有返回函数自身的名称的。

但是此时我换了一个文件,去调用这个装饰器,发现打印出来的函数名称,又变成装饰器自己的名称了。

百度了资料,并没有看到有使用 @wraps 还没有消除副作用的问题。于是就自己开始排查,确认自己封装的代码没有问题之后,于是就网上随便找了一个其他人的装饰器,发现也是这样。

当时内心就在想,为什么换个文件就不能打印函数的名称了,难道是我这里调用的代码有什么问题吗?

突然间就想到自己在这个函数上方封装了两个装饰器, @executionDuration(1000) 另外一个装饰器也是自己封装的,突然之间就觉得会不会是因为我封装了两个冲突了,于是就把另外一个装饰器去掉运行了一下,发现可以了。

确认是因为两个装饰器导致的,就好办了。于是我就尝试这把装饰器调整一下位置,把日志装饰器放在下面,发现可以了。


随后最后发现只是调整一下装饰器位置,但是中间排查问题,耗费了很长时间,网上关于这一块的资料几乎没有,希望这个思路可以帮助到你们~

以上是关于解决使用@wraps装饰器,但是仍然未消除装饰器产生的副作用问题的主要内容,如果未能解决你的问题,请参考以下文章

Python 中实现装饰器时使用 @functools.wraps 的理由

20181130(装饰器补充,叠加多个装饰器,有参装饰器,三元表达式,生成式,匿名函数,内置函数)

学习笔记2-functools.wraps 装饰器

python中装饰器修复技术

python修饰器(装饰器)以及wraps

functools.wraps 等价于类装饰器