AssertionError:视图函数映射正在覆盖现有端点函数:main

Posted

技术标签:

【中文标题】AssertionError:视图函数映射正在覆盖现有端点函数:main【英文标题】:AssertionError: View function mapping is overwriting an existing endpoint function: main 【发布时间】:2013-06-19 20:17:58 【问题描述】:

如果我有两个这样的 url 规则,有谁知道为什么我不能覆盖现有的端点函数

app.add_url_rule('/',
                 view_func=Main.as_view('main'),
                 methods=["GET"])

app.add_url_rule('/<page>/',
                 view_func=Main.as_view('main'),
                 methods=["GET"])

追溯:

Traceback (most recent call last): 
  File "demo.py", line 20, in <module> methods=["GET"]) 
  File ".../python2.6/site-packages/flask‌​/app.py", 
    line 62, in wrapper_func return f(self, *args, **kwargs) 
  File ".../python2.6/site-packages/flask‌​/app.py", 
    line 984, in add_url_rule 'existing endpoint function: %s' % endpoint)  
AssertionError: View function mapping is overwriting an existing endpoint 
    function: main

【问题讨论】:

你是在问你怎么能,或者你为什么能? 为什么它不起作用我正在学习教程 如果有人想知道为什么 Flask 有这种唯一视图名称的界限,请参阅我对类似问题的回答:***.com/a/47558985/4440675 这个答案解释了每个方法都有一个唯一名称背后的逻辑。 【参考方案1】:

当我在模块中有多个 API 函数并尝试用 2 个装饰器包装每个函数时,我也遇到了同样的问题:

    @app.route() 我的自定义 @exception_handler 装饰器

我得到了同样的异常,因为我试图用这两个装饰器包装多个函数:

@app.route("/path1")
@exception_handler
def func1():
    pass

@app.route("/path2")
@exception_handler
def func2():
    pass

具体来说,是因为尝试注册一些名为wrapper的函数:

def exception_handler(func):
  def wrapper(*args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        error_code = getattr(e, "code", 500)
        logger.exception("Service exception: %s", e)
        r = dict_to_json("message": e.message, "matches": e.message, "error_code": error_code)
        return Response(r, status=error_code, mimetype='application/json')
  return wrapper

更改函数的名称为我解决了它(wrapper.__name__ = func.__name__):

def exception_handler(func):
  def wrapper(*args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        error_code = getattr(e, "code", 500)
        logger.exception("Service exception: %s", e)
        r = dict_to_json("message": e.message, "matches": e.message, "error_code": error_code)
        return Response(r, status=error_code, mimetype='application/json')
  # Renaming the function name:
  wrapper.__name__ = func.__name__
  return wrapper

然后,装饰多个端点起作用了。

【讨论】:

也可以使用functools.wraps实现函数重命名。 我必须使用wrapper.__name__ 而不是wrapper.func_name。也许这是python2和python3的区别? 这是我使用装饰器的烧瓶 restful API 中的问题。 wrapper.__name__ = func.__name__ 在调用 wrapper 之前解决了问题。 感谢您的精彩解释和解决方案! 哇,这甚至是合法的哈哈。立即解决了我完全相同的问题。谢谢!【参考方案2】:

您的视图名称必须是唯一的,即使它们指向同一个视图方法。

app.add_url_rule('/',
                 view_func=Main.as_view('main'),
                 methods = ['GET'])

app.add_url_rule('/<page>/',
                 view_func=Main.as_view('page'),
                 methods = ['GET'])

【讨论】:

也就是说,.as_view($VIEW_NAME) 方法调用中的 $VIEW_NAME 应该作为唯一的字符串名称传入。【参考方案3】:

对于使用@app.route 的用户,最好使用键参数endpoint,而不是像Roei Bahumi 所述更改__name__ 的值。以他为例:

@app.route("/path1", endpoint='func1')
@exception_handler
def func1():
    pass

@app.route("/path2", endpoint='func2')
@exception_handler
def func2():
    pass

【讨论】:

这是一个很好的答案。我只想指出,不需要提供与实际函数名称相同的端点。只要没有冲突,您就可以在端点中放置任何内容。前任。我有一种情况,我正在使用高阶函数生成一个函数(3 次),我也必须生成端点名称以保持它们的唯一性。【参考方案4】:

Flask 要求您将单个“视图函数”与“端点”相关联。您正在调用 Main.as_view('main') 两次,这会创建两个不同的函数(完全相同的功能但内存签名不同)。短篇小说,你应该这样做

main_view_func = Main.as_view('main')

app.add_url_rule('/',
             view_func=main_view_func,
             methods=["GET"])

app.add_url_rule('/<page>/',
             view_func=main_view_func,
             methods=["GET"])

【讨论】:

【参考方案5】:

当您在不同的路由上具有相同的函数名称时,也会发生这种情况。

【讨论】:

这救了我,谢谢!我知道这很简单,但不确定出了什么问题(适合我复制函数)【参考方案6】:

我只想添加一个更“模板”类型的解决方案。

def func_name(f):
    def wrap(*args, **kwargs):
        if condition:
            pass
        else:
            whatever you want
        return f(*args, **kwargs)
    wrap.__name__ = f.__name__
    return wrap

想补充一篇我最近发现的非常有趣的文章“Demystifying Decorators”:https://sumit-ghosh.com/articles/demystifying-decorators-python/

【讨论】:

【参考方案7】:

在包装函数上方添加@wraps(f) 解决了我的问题。

def list_ownership(f):
    @wraps(f)
    def decorator(*args,**kwargs):
        return f(args,kwargs)
    return decorator

【讨论】:

【参考方案8】:

修复了最近引入的 Flask 问题 #570(flask 0.10),导致引发此异常。

见https://github.com/mitsuhiko/flask/issues/796

因此,如果您转到 flask/app.py 并注释掉 4 行 948..951,这可能会有所帮助,直到问题在新版本中完全解决。

更改的区别在这里:http://github.com/mitsuhiko/flask/commit/661ee54bc2bc1ea0763ac9c226f8e14bb0beb5b1

【讨论】:

回复:“直到问题在新版本中完全解决”:没有“问题”需要解决。正如问题讨论所示,在问题中的代码的情况下引发异常是预期的结果。正如接受的答案中所解释的,端点存在冲突。这是 Flask 用户的代码错误,而不是 Flask 本身。【参考方案9】:

如果您认为您有唯一的端点名称并且仍然给出此错误,那么您可能面临issue。我也是这样。

如果您有相同的版本,则此问题与烧瓶 0.10 相关,然后执行以下操作以摆脱此问题:

sudo pip uninstall flask
sudo pip install flask=0.9

【讨论】:

【参考方案10】:

即使它们指向同一个视图方法,您的视图名称也必须是唯一的,或者您可以添加 from functools import wraps 并使用 @wraps https://docs.python.org/2/library/functools.html

【讨论】:

【参考方案11】:

改用烧瓶 0.9 使用以下命令 sudo pip uninstall flask

sudo pip install flask==0.9

【讨论】:

【参考方案12】:

如果你在python notebook上使用flask,每次修改代码都需要重启内核

【讨论】:

【参考方案13】:

这对我来说是一个(破坏性)更新到 flask-jwt-extended(版本 4.xx 及更高版本),在我一年前编写的基本 api 中使用,现在正在合并进入一个项目。

@jwt_required 到 @jwt_required()

【讨论】:

这没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review

以上是关于AssertionError:视图函数映射正在覆盖现有端点函数:main的主要内容,如果未能解决你的问题,请参考以下文章

在 AssertionError 的情况下在“断言”之后执行代码

为定制的视图控制器覆盖非打开实例 swift

在 Python 中使用装饰器进行 AssertionError 异常处理

基于torch函数TransformerEncoder出现AssertionError问题的解决

Python AVRO阅读器在解码kafka消息时返回AssertionError

flask的路由