Discord后台任务读取JSON存储的频道ID发消息报10003未知频道错误
问题根因
- 内存中的
channels字典仅在程序启动时从JSON文件读取一次,后续JSON文件的改动不会自动同步到内存,get_general()始终返回启动时读取到的频道ID chanid在全局作用域仅赋值一次,属于固定常量,运行过程中不会自动更新- 频道对象
chan仅在循环开始前获取一次,后续ID更新后不会重新拉取有效频道对象 - 没有捕获发送消息的404异常,频道失效后会直接终止任务,不会触发ID重新读取逻辑
- 原有循环没有添加等待间隔,会高频重复发送消息直接触发接口限流
修复方案
import json import asyncio import discord try: with open("channels.json", 'r') as fp: channels = json.load(fp) except Exception: channels = {} def save_channels(): with open("channels.json", "w+") as fp: json.dump(channels, fp, indent=4) def get_general(): # 每次调用都重新读取最新的JSON文件,适配外部修改JSON的场景 try: with open("channels.json", 'r') as fp: latest_channels = json.load(fp) return latest_channels.get("general", 0) except Exception: return 0 async def hello_loop(): await client.wait_until_ready() while not client.is_closed(): # 每次循环都拉取最新ID、获取最新频道对象 chanid = get_general() chan = client.get_channel(chanid) if not chan: # 频道不存在,等待1分钟后重试 await asyncio.sleep(60) continue try: msg = 'hello' msgsend = await chan.send(msg) except discord.errors.NotFound: # 频道已失效,等待1分钟后重试 await asyncio.sleep(60) continue # 按需求设置发送间隔,示例为1小时发一次 await asyncio.sleep(3600) client.loop.create_task(hello_loop())
如果频道ID是本程序内部更新的,不需要每次都读文件,更新channels全局变量后,每次循环调用get_general()拉取最新值即可,可减少IO开销。
内容的提问来源于stack exchange,提问作者user10241025
相关产品推荐
相关产品推荐

