【问题标题】:Why python Flask decorator not logged?为什么没有记录 python Flask 装饰器?
【发布时间】:2020-07-24 07:59:32
【问题描述】:

我有一个简单的 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 flask decorator


    【解决方案1】:

    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
    

    【讨论】:

      【解决方案2】:

      您的打印声明在validate_request。尽管validate_request 返回一个装饰器,但它本身并不是一个装饰器。如果您愿意,它是一个 装饰器工厂,并且只执行一次以创建装饰器并在 python 加载您的代码时装饰 login,因此为什么您的打印语句只在您启动时执行一次服务器。请记住,装饰器本身也只执行一次,以将 login 替换为装饰器返回的任何内容,在本例中为 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-04
        • 2022-08-19
        • 2014-02-16
        • 2020-07-15
        • 2012-01-09
        • 2020-06-29
        • 2011-08-11
        • 2013-12-12
        相关资源
        最近更新 更多