ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

NoneBot2 事件处理常量全解析:nonebot.consts 模块深入指南

NoneBot2 事件处理常量全解析:nonebot.consts 模块深入指南 后端即时通讯【免费下载链接】nonebot2跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python项目地址https://gitcode.com/gh_mirrors/no/nonebot2点击查看免费下载导读nonebot.consts是 NoneBot2 框架中一个小而关键的模块它集中定义了事件处理过程中用于存取状态数据的全部常量键key。无论是Matcher.receive/got的多轮对话状态、pause/reject的暂停与重试机制还是命令、Shell 命令、正则、前缀/后缀/关键字等各类响应规则Rule的触发结果最终都以这些常量作为 key 写入事件响应器的state字典中。读完本文你将掌握每个常量的取值、类型、语义、在源码中的写入与读取位置以及如何通过nonebot.params中的依赖注入参数在插件中安全地消费这些状态数据。nonebot.consts模块的全部源码位于 nonebot/consts.py对应 2.4.3 版本的 API 文档为 website/versioned_docs/version-2.4.3/api/consts.md。本文以该文档列出的 24 个常量为骨架逐组拆解其底层实现与典型用法。一、模块定位事件响应器状态state的命名空间协议在 NoneBot2 中每个事件响应器Matcher都持有一个state: T_State字典用于在事件处理流程的各个阶段之间传递数据。nonebot.consts的全部常量本质上就是这套state字典的预留键名协议所有以_开头的键如_receive_{id}、_matched都是内部保留键插件自定义状态应避免与之冲突不含_前缀的键如command、command_arg虽然也由框架写入但语义上更接近解析产物同样不建议手动覆盖常量声明使用typing.Literal进行类型标注见 nonebot/consts.py让静态类型检查器能对state[key]的读写给出更精确的提示。从源码结构看这些常量按用途被划分为两大部分nonebot/consts.py 中的注释也明确标注了used by Matcher与used by Rule分组常量使用方Matcher 交互状态RECEIVE_KEY、LAST_RECEIVE_KEY、ARG_KEY、REJECT_TARGET、REJECT_CACHE_TARGET、PAUSE_PROMPT_RESULT_KEY、REJECT_PROMPT_RESULT_KEYnonebot/internal/matcher/matcher.pyRule 触发结果PREFIX_KEY、CMD_KEY、RAW_CMD_KEY、CMD_ARG_KEY、CMD_START_KEY、CMD_WHITESPACE_KEY、SHELL_ARGS、SHELL_ARGV、REGEX_MATCHED、STARTSWITH_KEY、ENDSWITH_KEY、FULLMATCH_KEY、KEYWORD_KEYnonebot/rule.py此外模块末尾还定义了一个与事件处理无直接关系的平台判断常量WINDOWS sys.platform.startswith(win) or (sys.platform cli and os.name nt)nonebot/consts.py用于在 Windows 与 CLRIronPython 等环境下做系统级判断它不属于本文讨论的事件处理常量范畴。二、Matcher 交互状态常量多轮对话与暂停/重试的存储协议这一组常量直接支撑 NoneBot2 的多轮会话机制全部由 nonebot/internal/matcher/matcher.py 读写。2.1 RECEIVE_KEY 与 LAST_RECEIVE_KEY接收事件的存取RECEIVE_KEY: Literal[_receive_{id}]——receive存储 keyLAST_RECEIVE_KEY: Literal[_last_receive]——last_receive存储 key。RECEIVE_KEY是带占位符{id}的模板实际使用时通过format(idid)生成具体键。在Matcher.receive()装饰器生成的依赖中nonebot/internal/matcher/matcher.pyasync def _receive(event: Event, matcher: Matcher) - None: matcher.set_target(RECEIVE_KEY.format(idid)) if matcher.get_target() RECEIVE_KEY.format(idid): matcher.set_receive(id, event) return if matcher.get_receive(id, ...) is not ...: return await matcher.reject()set_receive(id, event)将事件写入state[RECEIVE_KEY.format(idid)]同时更新state[LAST_RECEIVE_KEY]nonebot/internal/matcher/matcher.py因此LAST_RECEIVE_KEY永远指向最近一次接收的事件get_receive/get_last_receive分别读取这两个键nonebot/internal/matcher/matcher.py。典型应用Matcher.receive(id)配合依赖参数Received(id)与LastReceived()见 nonebot/params.py可实现先接收一次消息、再继续处理的流程。2.2 ARG_KEYgot 参数的存储协议ARG_KEY: Literal[{key}]——arg存储 key同样为带占位符模板。Matcher.got(key)的依赖逻辑nonebot/internal/matcher/matcher.pyasync def _key_getter(event: Event, matcher: Matcher): matcher.set_target(ARG_KEY.format(keykey)) if matcher.get_target() ARG_KEY.format(keykey): matcher.set_arg(key, event.get_message()) return if matcher.get_arg(key, ...) is not ...: return await matcher.reject(prompt)set_arg/get_arg分别写入、读取state[ARG_KEY.format(keykey)]nonebot/internal/matcher/matcher.py。插件侧可通过Arg(key)、ArgStr(key)、ArgPlainText(key)等依赖参数消费见 nonebot/params.py也可以直接用state[ARG_KEY.format(keykey)]手工读取。2.3 REJECT_TARGET 与 REJECT_CACHE_TARGETreject 目标定位REJECT_TARGET: Literal[_current_target]——当前reject目标存储 keyREJECT_CACHE_TARGET: Literal[_next_target]——下一个reject目标存储 key。这两个常量用于实现reject后重新从头执行当前处理函数的流程。set_target(target, cacheTrue)默认写入REJECT_CACHE_TARGETcacheFalse时写入REJECT_TARGETnonebot/internal/matcher/matcher.py。当事件被拒绝后resolve_reject()会把缓存目标提升为当前目标async def resolve_reject(self): handler current_handler.get() self.remain_handlers.insert(0, handler) if REJECT_CACHE_TARGET in self.state: self.state[REJECT_TARGET] self.state[REJECT_CACHE_TARGET]见 nonebot/internal/matcher/matcher.py这样get_target()就能准确判断本次重试是针对哪个 receive/arg 目标从而决定是直接继续还是重新等待用户输入。测试用例中也能看到matcher.set_target(RECEIVE_KEY.format(idtest), cacheFalse)的用法tests/test_param.py。2.4 PAUSE_PROMPT_RESULT_KEY 与 REJECT_PROMPT_RESULT_KEYprompt 发送结果PAUSE_PROMPT_RESULT_KEY: Literal[_pause_result]——pauseprompt 发送结果存储 keyREJECT_PROMPT_RESULT_KEY: Literal[_reject_{key}_result]——rejectprompt 发送结果存储 key。当Matcher.pause(prompt)或Matcher.reject(prompt)携带提示消息时send()的返回结果会被写入 statenonebot/internal/matcher/matcher.py 与 nonebot/internal/matcher/matcher.py# pause 分支 if matcher is not None: matcher.state[PAUSE_PROMPT_RESULT_KEY] result # reject 分支 key REJECT_PROMPT_RESULT_KEY.format(keykey) if key is not None else None if prompt is not None: result await cls.send(prompt, **kwargs) if key is not None and matcher: matcher.state[key] result同样reject_arg(key, prompt)与reject_receive(id, prompt)也会把发送结果写入REJECT_PROMPT_RESULT_KEY.format(keyarg_key)/format(keyreceive_key)nonebot/internal/matcher/matcher.py。插件侧可通过PausePromptResult()与ReceivePromptResult(id)依赖参数直接获取nonebot/params.py在后续处理中复用提示消息是否成功送达等发送结果通常是适配器Bot.send的返回值具体字段由各适配器决定。三、命令解析常量PREFIX_KEY 及其五个子键命令规则on_command在 nonebot/rule.py 的TrieRule.get_value中完成解析解析结果统一存放在state[PREFIX_KEY]这个CMD_RESULT字典里。CMD_RESULT是一个TypedDictnonebot/rule.py其五个字段正好对应五个命令子键class CMD_RESULT(TypedDict): command: tuple[str, ...] | None # CMD_KEY raw_command: str | None # RAW_CMD_KEY command_arg: Message | None # CMD_ARG_KEY command_start: str | None # CMD_START_KEY command_whitespace: str | None # CMD_WHITESPACE_KEY各常量含义与写入位置常量值说明写入位置PREFIX_KEY_prefix命令前缀存储 key整个解析结果的容器nonebot/rule.pyCMD_KEYcommand命令元组存储 key如(test,)nonebot/rule.pyRAW_CMD_KEYraw_command命令文本存储 key如/testnonebot/rule.pyCMD_ARG_KEYcommand_arg命令参数存储 key剩余消息段nonebot/rule.pyCMD_START_KEYcommand_start命令开头存储 key如/nonebot/rule.pyCMD_WHITESPACE_KEYcommand_whitespace命令与参数间空白符存储 keynonebot/rule.py解析流程核心逻辑nonebot/rule.pystate[PREFIX_KEY] prefix if event.get_type() ! message: return prefix message event.get_message() message_seg: MessageSegment message[0] if message_seg.is_text(): segment_text str(message_seg).lstrip() if pf : cls.prefix.longest_prefix(segment_text): value: TRIE_VALUE pf.value prefix[RAW_CMD_KEY] pf.key prefix[CMD_START_KEY] value.command_start prefix[CMD_KEY] value.command ... prefix[CMD_ARG_KEY] msg要点命令前缀通过TrieRule.add_prefix注册进一个CharTrie字符前缀树nonebot/rule.pylongest_prefix保证最长前缀优先匹配非message类型事件如元事件、通知事件不会触发命令解析prefix保持全空字段命令与参数之间的空白符会被单独截取存入CMD_WHITESPACE_KEYnonebot/rule.py参数部分则重组为新的消息对象存入CMD_ARG_KEY。插件侧对应的一组依赖参数位于 nonebot/params.pyCommand()、RawCommand()、CommandArg()、CommandStart()、CommandWhitespace()实现均为state[PREFIX_KEY][对应子键]的一行读取。四、Shell 命令常量SHELL_ARGS 与 SHELL_ARGVShell 命令规则on_shell_command在ShellCommandRule.__call__中完成解析nonebot/rule.py涉及两个常量SHELL_ARGS: Literal[_args]——shell 命令 parse 后参数字典存储 keySHELL_ARGV: Literal[_argv]——shell 命令原始参数列表存储 key。解析流程用shlex.split把命令参数文本切分为原始参数列表文本段切分、非文本段如图片MessageSegment原样保留存入state[SHELL_ARGV]若提供ArgumentParser则用parser.parse_args(state[SHELL_ARGV])解析Namespace结果存入state[SHELL_ARGS]解析失败时ArgumentError/ParserExit存入的是ParserExit异常对象且state[SHELL_ARGV]可能被置为Nonenonebot/rule.py。这一点在测试中得到了完整覆盖tests/test_rule.py无参数时state[SHELL_ARGV] []且SHELL_ARGS不存在shlex切分失败时SHELL_ARGV is None解析失败时SHELL_ARGS为ParserExit且status ! 0缺参/非法参数或status 0如-h帮助请求混合消息段如MessageSegment.image(test)会保留在参数列表中。插件侧通过ShellCommandArgv()原始参数列表与ShellCommandArgs()解析后Namespace或ParserExit消费nonebot/params.py。注意文档中的警告如果参数解析失败ShellCommandArgs获取到的将是ParserExit异常而非Namespace需要在插件中自行判空与异常处理。五、文本匹配规则常量REGEX_MATCHED 与 前缀/后缀/全匹配/关键字这五个常量由 nonebot/rule.py 中对应的文本规则写入供插件通过nonebot.params依赖参数读取。5.1 REGEX_MATCHED正则匹配结果REGEX_MATCHED: Literal[_matched]——正则匹配结果存储 key。RegexRule.__call__使用re.search注意不是match如需从头匹配须自行加^对消息的str表示进行搜索命中后将re.Match对象写入state[REGEX_MATCHED]nonebot/rule.py。插件侧对应依赖参数nonebot/params.pyRegexMatched()——返回Match[str]对象RegexStr(*groups)——返回match.group(*groups)的文本RegexGroup()——返回match.groups()元组RegexDict()——返回match.groupdict()字典。测试中通过构造fake_matched验证了这些依赖参数的读取行为tests/test_param.py。5.2 STARTSWITH_KEY / ENDSWITH_KEY / FULLMATCH_KEY / KEYWORD_KEYSTARTSWITH_KEY: Literal[_startswith]——响应触发前缀 keyENDSWITH_KEY: Literal[_endswith]——响应触发后缀 keyFULLMATCH_KEY: Literal[_fullmatch]——响应触发完整消息 keyKEYWORD_KEY: Literal[_keyword]——响应触发关键字 key。各自的写入逻辑规则匹配方式写入内容源码位置StartswithRulere.match匹配开头可ignorecase实际匹配到的前缀文本nonebot/rule.pyEndswithRulere.search匹配结尾可ignorecase实际匹配到的后缀文本nonebot/rule.pyFullmatchRule纯文本与候选串全等casefold忽略大小写匹配到的完整文本nonebot/rule.pyKeywordsRule纯文本包含任一关键字命中的第一个关键字nonebot/rule.py对应依赖参数为Startswith()、Endswith()、Fullmatch()、Keyword()nonebot/params.py。一个典型用途在on_startswith(你好)的处理器中通过Startswith()拿到实际触发的前缀文本例如用户发送了你好呀则拿到你好实现更精细的响应。六、实践在插件中组合使用这些常量6.1 直接读取 state 的逃生通道虽然nonebot.params提供了大部分依赖参数但框架本身并不禁止插件直接访问state。例如在Matcher.got(city)之后from nonebot import on_command from nonebot.consts import ARG_KEY, CMD_KEY matcher on_command(weather) matcher.got(city, prompt请输入城市名) async def handle(city: str ArgStr(city)): # 等价于 state[ARG_KEY.format(keycity)] ...在自定义依赖函数中ARG_KEY、RECEIVE_KEY等模板常量也能帮助你精确读写指定槽位而不必硬编码_receive_xxx这类字符串。6.2 组合命令参数与 arg 状态一个综合示例命令 多轮补参同时读取命令元组与 got 参数from nonebot import on_command from nonebot.params import Command, ArgStr matcher on_command(order) matcher.got(item, prompt请输入商品名) async def create_order( cmd: tuple[str, ...] Command(), # 从 state[PREFIX_KEY][CMD_KEY] 读取 item: str ArgStr(item), # 从 state[ARG_KEY.format(keyitem)] 读取 ): await matcher.send(f命令 {cmd} 已收到商品 {item})6.3 编写自定义规则时遵循常量协议若需要编写自定义规则并在state中写入数据应复用现有常量键或遵循其命名风格以保证与内置依赖参数、后续处理阶段兼容。例如自定义一个天气关键字规则时可以参照KeywordsRule的写法把命中词写入state[KEYWORD_KEY]nonebot/rule.py这样插件中直接用Keyword()就能拿到结果。七、速查总表常量字面值用途分组主要读写位置RECEIVE_KEY_receive_{id}Matchernonebot/internal/matcher/matcher.pyLAST_RECEIVE_KEY_last_receiveMatchernonebot/internal/matcher/matcher.pyARG_KEY{key}Matchernonebot/internal/matcher/matcher.pyREJECT_TARGET_current_targetMatchernonebot/internal/matcher/matcher.pyREJECT_CACHE_TARGET_next_targetMatchernonebot/internal/matcher/matcher.pyPAUSE_PROMPT_RESULT_KEY_pause_resultMatchernonebot/internal/matcher/matcher.pyREJECT_PROMPT_RESULT_KEY_reject_{key}_resultMatchernonebot/internal/matcher/matcher.pyPREFIX_KEY_prefixRulenonebot/rule.pyCMD_KEYcommandRulenonebot/rule.pyRAW_CMD_KEYraw_commandRulenonebot/rule.pyCMD_ARG_KEYcommand_argRulenonebot/rule.pyCMD_START_KEYcommand_startRulenonebot/rule.pyCMD_WHITESPACE_KEYcommand_whitespaceRulenonebot/rule.pySHELL_ARGS_argsRulenonebot/rule.pySHELL_ARGV_argvRulenonebot/rule.pyREGEX_MATCHED_matchedRulenonebot/rule.pySTARTSWITH_KEY_startswithRulenonebot/rule.pyENDSWITH_KEY_endswithRulenonebot/rule.pyFULLMATCH_KEY_fullmatchRulenonebot/rule.pyKEYWORD_KEY_keywordRulenonebot/rule.py所有常量均以Literal[...]标注类型并定义于 nonebot/consts.py是连接 nonebot/internal/matcher/matcher.py、nonebot/rule.py、nonebot/params.py 三个模块的状态键协议。理解这套常量是深入 NoneBot2 事件处理管线、编写自定义规则与多轮会话插件的重要基础。赞分享后端即时通讯【免费下载链接】nonebot2跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python项目地址https://gitcode.com/gh_mirrors/no/nonebot2点击查看免费下载相关推荐用MOOTDX构建Python量化分析系统通达信数据读取终极解决方案用MOOTDX构建Python量化分析系统通达信数据读取终极解决方案 在量化投资领域数据获取一直是技术门槛最高的环节之一。MOOTDX作为通达信数据读取的P金融科技数据分析163MusicLyrics构建跨平台音乐元数据聚合框架的技术实现163MusicLyrics构建跨平台音乐元数据聚合框架的技术实现 价值定位与问题域定义 在数字音乐内容管理领域元数据聚合与标准化处理构成了一个复杂的技术挑桌面应用音视频终极指南在Android设备上快速运行Windows应用的5个简单步骤终极指南在Android设备上快速运行Windows应用的5个简单步骤 在移动设备上运行Windows x86应用程序曾经听起来像是天方夜谭但Mobox项目虚拟化CLI上一篇KMS智能激活工具完整指南一键永久激活Windows与Office下一篇Windows 11 LTSC系统如何快速恢复微软商店告别应用荒的终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表