You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask.route()触发TypeError:意外关键字参数问题解惑

Flask装饰器参数匹配问题解析

问题背景

编写了一个猜数字的Flask应用,根路由可正常加载,但访问带数字的路由(如/1)时抛出TypeError: wrapper_function() got an unexpected keyword argument 'number'错误。

原Flask代码

from flask import Flask
from random import randint

rand_n = randint(0, 9)
app = Flask(__name__)


def decorator_header(function):
    def wrapper():
        return f"<h1>{function()}</h1>"
    return wrapper


def check_decorator(function):
    def wrapper_function(*args):
        result = function(args[0])
        if result == "You found me!":
            return f"<b style='color:green;'>{result}</b>"
        if result == "Too low, try again!":
            return f"<b style='color:red;'>{result}</b>"
        return f"<b style='color:purple;'>{result}</b>"
    return wrapper_function


@app.route('/')
@decorator_header
def guess_number():
    return 'Guess a number between 0 and 9'


@app.route('/<number>', endpoint='check_number')
@check_decorator
def check_number(number):
    if int(number) < rand_n:
        return "Too low, try again!"
    if int(number) > rand_n:
        return "Too high, try again!"
    return "You found me!"


if __name__ == "__main__":
    app.run()

错误信息

[2023-02-19 21:16:23,710] ERROR in app: Exception on /1 [GET]
Traceback (most recent call last):
  File "C:\Users\pauLo\venv\lib\site-packages\flask\app.py", line 2528, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\pauLo\venv\lib\site-packages\flask\app.py", line 1825, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\pauLo\venv\lib\site-packages\flask\app.py", line 1823, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\pauLo\venv\lib\site-packages\flask\app.py", line 1799, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
TypeError: wrapper_function() got an unexpected keyword argument 'number'
127.0.0.1 - - [19/Feb/2023 21:16:23] "GET /1 HTTP/1.1" 500 -

特殊现象

  • 将装饰器的wrapper_function参数改为number后可正常运行,用其他名称仍报错;
  • 脱离Flask环境运行原装饰器代码无问题:
@decorator_header
def guess_number():
    return 'Guess a number between 0 and 9'


@check_decorator
def check_number(number):
    if int(number) < rand_n:
        return "Too low, try again!"
    if int(number) > rand_n:
        return "Too high, try again!"
    return "You found me!"


guess = input(guess_number())
print(check_number(guess))

原因分析

没错,Flask确实会以关键字参数的形式传递路由参数。当访问/1时,Flask解析出路由参数number=1,调用视图函数时会执行check_number(number=1)。

原装饰器的wrapper_function只定义了*args,这只能处理位置参数,无法接收关键字参数,因此抛出“意外关键字参数”的错误。而脱离Flask环境时,你是用位置参数调用check_number(guess),*args能正常捕获参数,所以不会报错。

当你把wrapper_function的参数改为number时,它就可以接收number=1这个关键字参数,自然能正常运行。

正确解决方案

要让装饰器兼容Flask的关键字参数传递,需要让包装函数同时支持位置参数和关键字参数,修改check_decorator为:

def check_decorator(function):
    def wrapper_function(*args, **kwargs):
        result = function(*args, **kwargs)
        if result == "You found me!":
            return f"<b style='color:green;'>{result}</b>"
        if result == "Too low, try again!":
            return f"<b style='color:red;'>{result}</b>"
        return f"<b style='color:purple;'>{result}</b>"
    return wrapper_function

这种写法直接把接收到的所有参数原封不动传给原函数,不管Flask用位置参数还是关键字参数传递,装饰器都能正常处理,不需要硬编码参数名number。


内容的提问来源于stack exchange,提问作者Miqueias Brikalski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:25:43