模块化

我现在是这样的

Bot:
└─config
└─db
└─modules
└─utils
  • config内包含所有模块用到的配置项

  • db内是实体类和业务语句的集合

  • utils内是一些公共工具

现在问题是,config与db非常难维护,一打开就是几百行语句,找起来都麻烦,数据库和配置项有一点不对整个bot就无法启动

依照模块化的思想,所有与具体module有关的类都应在它自己的文件夹下,做到方便维护,Bot主体可以实现扩展并管理配置文件和database,甚至做到overload(很难),这些是一开始写时没有想到的。

实体类与pydantic重复

写db相关经常会构建两个差不多的类,一个数据库实体类,一个装载它的pydantic模型类,其实可以直接使用sqlmodel这个依赖进行一次性构建

pip install sqlmodel
from typing import Optional

from sqlmodel import Field, SQLModel


class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    secret_name: str
    age: Optional[int] = None

非常方便

文档:SQLModel (tiangolo.com)

生命周期管理

很多模块有争对用户的功能,那就要做到基本的用户增删改查,以及给管理员的增删改查,不要想着偷懒,后面出问题会非常难受

有些单例有初始化方法,初始化的位置与是否async要考虑好,常用的类可以交给launart管理

from launart import ExportInterface, Launchable


class TestService(Launchable):
    id: str = "test/init"

    @property
    def required(self) -> set[str | type[ExportInterface]]:
        return set()

    @property
    def stages(self) -> set[str]:
        return {"preparing", "cleanup"}

    async def launch(self, _):
        print("before preparing")
        async with self.stage("preparing"):
            print("preparing")
        print("before cleanup")
        async with self.stage("cleanup"):
            print("cleanup")
        print("after cleanup")

交给launart就不用担心sync与async的冲突问题,还可以方便的获得具体的Service实例

统一Session

bot作为工具的集成,许多功能是需要发送get/post请求获取信息的,统一的Session可以节省一些开支,但是会区分用户以及cookies的功能需要注意,不然单例的Session在async的使用上会出现不可预知的错误,包括用户对不上等等

依赖过重

一些基本的功能可以写个request就可以替代,却非得拉个库来实现,例如为了bilibili的视频解析而引入了biliapi,就导致了aiohttp的依赖冲突问题