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

本文介绍Sanic服务启动失败的问题及其解决方案。主要原因是路由注册时机不当,文章提供了正确的路由注册方式,并解释了如何避免此类错误。

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()
在C语言编写的服务启动过程中,若出现数据库查询请求失败并提示“数据被截断”的错误,通常与数据库操作中的字段长度限制、数据类型不匹配或约束条件未满足有关。以下从多个角度分析可能的原因及解决方法: ### 1. 数据字段长度限制问题 数据库表中定义的字段(如 `VARCHAR`、`CHAR` 等)具有最大长度限制,如果 C 语言服务在插入或更新数据时超出了该限制,数据库将拒绝操作并提示“数据被截断”。例如,某字段定义为 `VARCHAR(255)`,但实际传入的字符串长度超过 255 字符时,就会触发该错误。 建议检查数据库表结构定义,并确认 C 语言代码中传入的字符串长度是否符合字段限制。可使用 `strncpy()` 等函数进行长度控制,或在插入前进行长度校验。 ```c char input[256]; strncpy(input, user_input, sizeof(input) - 1); input[sizeof(input) - 1] = '\0'; // 确保字符串以 '\0' 结尾 ``` ### 2. 数据类型不匹配 在执行数据库查询时,若 C 语言服务传入的数据类型与数据库表定义的字段类型不一致,也可能导致数据被截断。例如,将字符串插入到 `INT` 类型字段中,或向 `DATE` 字段插入格式错误的日期字符串,数据库可能尝试隐式转换失败,从而导致截断。 应确保 C 语言代码中绑定的参数类型与数据库字段类型严格匹配。例如,在使用 `libpq` 连接 PostgreSQL 时,确保使用正确的类型转换函数,如 `PQsetdbLogin` 和 `PQexecParams` 等接口时指定参数类型。 ### 3. 数据库约束与触发器限制 某些数据库表可能设置了约束(如唯一性约束、外键约束)或触发器,在服务启动时进行的初始化查询可能违反这些约束,导致数据库拒绝操作并提示错误。例如,尝试插入重复的主键值,或触发器逻辑中对输入数据进行了额外校验并抛出异常。 建议查看数据库日志或错误信息,确认是否因违反约束导致操作失败,并根据具体情况调整插入逻辑或数据内容。 ### 4. 客户端与数据库字符集不一致 若 C 语言服务使用的字符集与数据库字符集不一致,可能导致多字节字符(如 UTF-8 中的中文字符)在传输过程中被错误解析,从而超出字段长度限制或出现非法字符,进而导致截断错误。 应确保数据库连接字符串中指定了正确的字符集,例如在使用 MySQL Connector/C 时,可通过如下方式设置字符集: ```c mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8mb4"); ``` ### 5. 使用参数化查询避免 SQL 注入和格式错误 直接拼接 SQL 语句可能导致格式错误或截断问题,建议使用参数化查询(Prepared Statements)来提高安全性与兼容性。例如,在使用 SQLite 时可使用如下方式: ```c sqlite3_stmt *stmt; const char *sql = "INSERT INTO users (name, email) VALUES (?, ?);"; sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC); sqlite3_step(stmt); sqlite3_finalize(stmt); ``` ### 6. 日志与调试信息分析 建议启用数据库的详细日志功能,捕获具体的错误信息,例如 PostgreSQL 的 `log_statement` 或 MySQL 的 `general_log`,以便定位具体的 SQL 语句和出错原因。同时,在 C 语言服务中增加日志输出,记录数据库连接、查询执行状态,便于排查问题。 ### 7. 数据库连接配置问题 服务启动时若数据库连接配置错误(如主机名、端口、用户名、密码等),可能导致连接失败,后续的查询操作自然也无法执行。建议检查配置文件或环境变量中数据库连接参数的正确性,并使用命令行工具(如 `psql` 或 `mysql`)手动测试连接。 ### 8. 数据库服务启动或网络问题 在服务启动时,若目标数据库服务未运行或网络不通,也可能导致查询失败。建议确认数据库服务状态,并检查网络连通性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值