Sanic服务启动失败,报错Cannot finalize with no routes defined

Sanic服务启动失败,记录解决方法

问题描述

Sanic服务启动失败,同样的代码和python版本在之前的win10系统上运行的好好的,换了台win11的机器就跑不起来了,不知道是系统原因还是因为换了执行pycharm等其他原因

在尝试启动时总是会报类似如下的错误:

sanic_routing.exceptions.FinalizationError: Cannot finalize with no routes defined.
sys:1: RuntimeWarning: coroutine ‘BaseEventLoop.create_server’ was never awaited

报错部分截图:
在这里插入图片描述
运行环境:

  • win11
  • pycharm
  • python3.9

运行方式:

  • debug方式或普通右键方式运行
尝试找到原因并解决

发现的表象原因:
sanic服务注册路由时放在了函数中执行会导致路由在app启动时还没有注册,从而导致启动失败
sanic关闭服务时也会检测是否注册路由,如果没有路由就会报上面提到的错误:Cannot finalize with no routes defined.
例如下图中的

# -*- coding:utf-8 -*-
from sanic import response, Sanic
from sanic.views import HTTPMethodView


app = Sanic("abc")


class NameTest(HTTPMethodView):

    @classmethod
    async def post(cls, request):
        print(cls.post.__name__)
        return response.text("test")
        

def register_route():
    # 注册路由放到了方法中,如果用这种方式,会导致启动失败
    app.add_route(NameTest.as_view(), "/test")


if __name__ == '__main__':
    register_route()
    app.run()

可以正确启动的方式:
是把注册路由相关的方法(blueprint、add_router这些)放到app所在的全局处理:

# -*- coding:utf-8 -*-
from sanic import response, Sanic
from sanic.views import HTTPMethodView


app = Sanic("abc")


class NameTest(HTTPMethodView):

    @classmethod
    async def post(cls, request):
        print(cls.post.__name__)
        return response.text("test")


# 注册路由放在了全局执行
app.add_route(NameTest.as_view(), "/test")


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

找到了表象原因,代码不多可以通过将注册路由的时机放到全局启动时来解决这个问题
但是如果是在工作项目中,已经写好了大部分的的路由注册方式(而且大概率会在方法中执行路由注册)

更新,根本原因及解决方法

在sanic github的一个issue找到的部分原因和线索:
对app的任何操作(例如,注册路由/创建蓝图/更新配置等)都必须在if __name__ == '__main__'之前完成,在if __name__ == '__main__'对app的操作只能时app.run

因此解决办法就是把app.run的其他操作都在if __name__ == '__main__'之前做完即可
例如,在if __name__ == '__main__'之前先运行路由注册

# -*- coding:utf-8 -*-
# -*- coding:utf-8 -*-
from sanic import response, Sanic
from sanic.views import HTTPMethodView


app = Sanic("abc")


class NameTest(HTTPMethodView):

    @classmethod
    async def post(cls, request):
        print(cls.post.__name__)
        return response.text("test")


def register_route():
    app.add_route(NameTest.as_view(), "/test")

register_route()


if __name__ == '__main__':
    app.run()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值