TypeError:Python 装饰器的意外关键字参数

Posted

技术标签:

【中文标题】TypeError:Python 装饰器的意外关键字参数【英文标题】:TypeError: unexpected keyword argument with Python Decorator 【发布时间】:2018-02-23 15:41:34 【问题描述】:

我收到以下类型错误:

TypeError: wrapper() got an unexpected keyword argument 'id'

当我尝试使用这些装饰器执行功能时:

def owner_required(table):
    def tags_decorator(func):
        @wraps(func) # this requires an import
        def wrapper(id):
            user_profile = (session['username'], session['picture'])
            # Connect to the database
            con = connect()
            Base.metadata.bind = con
            # Creates a session
            DBSession = sessionmaker(bind=con)
            dbsession = DBSession()
            if table == 'incidents':
                query = dbsession.query(Incidents).
                    filter_by(case_num=id).first()
            if table == 'audits':
                query = dbsession.query(Audits).filter_by(id=id).first()
            if table == 'actions':
                query = dbsession.query(Actions).filter_by(id=id).first()

            creator = int(query.user_id)
            ses_user = int(session['user_id'])
            if 'username' not in session or creator != ses_user:
                flash("Sorry, %s,"
                      " you are not authorized to edit this incident." %
                      session['username'])
                return redirect('/incidents/')
            else:
                func()
        return wrapper
    return tags_decorator

def check_if_report_exists(table):
    def tags_decorator(func):
        @wraps(func) # this requires an import
        def wrapper(**kwargs):
            # Connect to the database
            con = connect()
            Base.metadata.bind = con
            # Creates a session
            DBSession = sessionmaker(bind=con)
            dbsession = DBSession()
            if table == 'incidents':
                query = dbsession.query(Incidents).filter_by(case_num=id).first()
            if table == 'audits':
                query = dbsession.query(Audits).filter_by(id=id).first()
            if table == 'actions':
                query = dbsession.query(Actions).filter_by(id=id).first()
            if query is None:
                flash("Sorry, %s,"
                      " this report does not exists" %
                      session['username'])
                return redirect('/dashboard/')
            else:
                 func(**kwargs)
        return wrapper
    return tags_decorator

这是带有装饰器的函数:

app.route('/incidents/edit/<int:id>/', methods=['GET', 'POST'])
@login_required
@owner_required('incidents')
@check_if_report_exists('incidents')
def editIncident(id):
    some code...

本质上,路由传递一个整数给函数,使用 Flask 调用具有正确信息的页面。我需要在装饰器中使用相同的数字,以确保登录的用户是创建页面供他们编辑的用户。

我一直在关注 this guide 到装饰器,特别是关于将参数传递给装饰器的部分。

【问题讨论】:

对于装饰器,将其包装(*args,**kwargs)作为签名。并将参数传递给 func(*args, **kwargs),在您的代码中,您只需编写 func() 我不认为你可以像现在这样堆叠你的装饰器。最后一个,check_if_report_exists,是返回一个函数的函数,其中id 给出了一个TypeError。我认为没有所有代码就无法分辨。 我尝试添加 *args 和 **kwargs 但收到相同的错误。我编辑了原始帖子以包含其他装饰器的代码,并更好地解释了我要完成的工作。 这里是 git 仓库:github.com/JTP709/SMS 【参考方案1】:

这是一个愚蠢的错误——我太专注于错误的装饰器。 @login_required 没有传递任何参数。

我通过将 (*args, **kwargs) 传递给包装器和函数来解决它:

def login_required(session):
    def tags_decorator(func):
        @wraps(func) # this requires an import
        def wrapper(*args, **kwargs):
            logger.info('Checking if user in logged in.')
            if 'username' not in session:
                logger.info('User is not logged in.')
                return redirect('login')
            else:
                logger.info('User is logged in.')
                return func(*args, **kwargs)
        return wrapper
    return tags_decorator

我犯的另一个错误是没有返回 func(),所以我收到了一个视图错误。我假设这是因为我使用的是 Python 3。

【讨论】:

以上是关于TypeError:Python 装饰器的意外关键字参数的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:传递给优化器的意外关键字参数:learning_rate

Python TypeError:reduce_noise() 得到了一个意外的关键字

TypeError: scatter() 得到了一个意外的关键字参数“trendline_options”(Plotly,Python)

JS 装饰器的 ESLint 意外字符“@”

装饰器的意外行为[重复]

TypeError:attrib() 得到了一个意外的关键字参数“convert”