为什么 python Flask 装饰器没有记录?

Why python Flask decorator not logged?

我有一个简单的 Flask 应用程序,我想用这样的装饰器验证 json 格式的请求:

def validate_request(*expected_args):
    """
    Validate requests decorator
    """
    # print('=======================ENTER VALIDATE_REQUEST================')
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            json_obj = request.get_json()
            for expected_arg in expected_args:
                if expected_arg not in json_obj or json_obj.get(expected_arg) is None:
                    return api_response({'error': f"You must call with all request params: {', '.join(expected_args)}"})
            return func(*args, **kwargs)
        return wrapper
    return decorator

在路由端是这样的:

@user_api.route('/login', methods=['POST'])
@validate_request('email', 'password')
def login():
    req_data = request.get_json()
......................

我的问题是为什么当我调用 '/login' 路由时装饰器的 PRINT 语句没有显示?

仅当我启动服务器(flask 运行)时才会记录该消息。

谢谢。

Python 装饰器替换了它们正在装饰的函数。当解释器读取代码时,此替换发生在程序开始时。这是您的打印语句将被执行的时间。这段时间之后,返回的函数是唯一会 运行 的代码。如果你想在每次调用时打印到 运行,你需要放入将被调用的实际函数:

def validate_request(*expected_args):
    """
    Validate requests decorator
    """
    # print('=======================Function Decoration Happening================')
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            print("==== ENTER VALIDATE_REQUEST ===")
            json_obj = request.get_json()
            for expected_arg in expected_args:
                if expected_arg not in json_obj or json_obj.get(expected_arg) is None:
                    return api_response({'error': f"You must call with all request params: {', '.join(expected_args)}"})
            return func(*args, **kwargs)
        return wrapper
    return decorator

您的打印语句在 validate_request 中。 validate_requestreturns虽然是装饰器,但它本身并不是装饰器。如果你愿意,它是一个 装饰器工厂 ,并且只执行一次以创建装饰器并在 python 加载你的代码时装饰 login,因此为什么你的 print 语句仅在启动服务器时执行一次。请记住,装饰器本身也只执行一次以将 login 替换为任何装饰器 returns,在本例中为 wrapper。因此,wrapper 是将在每个请求上调用的实际函数。如果您将打印语句放在那里,您将在每个请求中看到它。

def validate_request(*expected_args):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            print("=== Enter validate request ===")
            return func(*args, **kwargs)
        return wrapper
    return decorator