Discord机器人command_prefix为NoneType的TypeError求助
Discord机器人前缀获取报错修复方案
问题背景
SQL基础薄弱,但判断问题并非出自SQL。Discord机器人曾正常运行一次,之后突然失效,抛出如下错误:
错误堆栈
Traceback (most recent call last): File "C:\Users\Mahdiyar\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\bot.py", line 1199, in get_prefix ret = list(ret) # type: ignore ^^^^^^^^^ TypeError: 'NoneType' object is not iterable During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\Mahdiyar\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\client.py", line 409, in _run_event await coro(*args, **kwargs) File "C:\Users\Mahdiyar\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\bot.py", line 1394, in on_message await self.process_commands(message) File "C:\Users\Mahdiyar\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\bot.py", line 1389, in process_commands ctx = await self.get_context(message) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Mahdiyar\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\bot.py", line 1288, in get_context prefix = await self.get_prefix(origin) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Mahdiyar\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\bot.py", line 1206, in get_prefix raise TypeError( TypeError: command_prefix must be plain string, iterable of strings, or callable returning either of these, not NoneType
涉事代码
async def get_prefix(client, message): async with aiosqlite.connect("sqlite2023.db") as db: async with db.cursor() as cursor: await cursor.execute('SELECT prefix FROM prefix WHERE guild = ?' , (message.guild.id,)) data = await cursor.fetchone() if data: return data else: try: await cursor.execute('INSERT INTO prefix (prefix, guild) VALUES (? , ?)', ('!', message.guild.id,)) await cursor.execute('SELECT prefix FROM prefix WHERE guild = ?' , (message.guild.id,)) data = await cursor.fetchone() if data: cursor.execute('UPDATE prefix SET prefix = ? WHERE guild = ? ' , ('!',message.guild.id,)) except Exception: return '!' @client.event #Client Statusa async def on_ready(): forever_print.start() asyncio.create_task(rich_presence()) print("Client is online!") async with aiosqlite.connect("sqlite2023.db") as db: async with db.cursor() as cursor: await cursor.execute('CREATE TABLE IF NOT EXISTS prefix (prefix TEXT ,guild ID)') await db.commit()
问题诊断
- 函数返回值缺失:
get_prefix的else分支中,若插入数据未触发异常,函数没有明确返回值,默认返回None,直接违反Discord.py对前缀的类型要求。 - 返回值类型错误:
fetchone()返回元组(如('!',)),直接返回元组会被当作前缀列表处理,不符合预期,应返回字符串类型的前缀。 - 数据库操作不完整:
INSERT执行后未调用await db.commit(),数据未持久化,下次查询仍返回空。 - 表结构语法错误:
CREATE TABLE中的guild ID是无效语法,Discord服务器ID为整数,应定义为guild INTEGER。 - 无效冗余操作:
INSERT成功后执行UPDATE完全多余,且该操作未加await,会引发异步错误。
修复代码
async def get_prefix(client, message): # 处理私信场景,避免message.guild为None报错 if not message.guild: return '!' async with aiosqlite.connect("sqlite2023.db") as db: async with db.cursor() as cursor: await cursor.execute('SELECT prefix FROM prefix WHERE guild = ?', (message.guild.id,)) data = await cursor.fetchone() if data: # 返回元组中的字符串前缀 return data[0] else: try: # 插入默认前缀 await cursor.execute('INSERT INTO prefix (prefix, guild) VALUES (? , ?)', ('!', message.guild.id)) # 提交更改确保数据持久化 await db.commit() return '!' except Exception as e: # 打印异常便于调试 print(f"插入前缀失败: {str(e)}") return '!' @client.event async def on_ready(): forever_print.start() asyncio.create_task(rich_presence()) print("Client is online!") async with aiosqlite.connect("sqlite2023.db") as db: async with db.cursor() as cursor: # 修正表结构,guild字段类型为INTEGER await cursor.execute('CREATE TABLE IF NOT EXISTS prefix (prefix TEXT, guild INTEGER)') await db.commit()
关键修复点
- 补全所有分支的返回值,确保函数不会返回
None。 - 将
fetchone()的返回值从元组改为字符串(取第一个元素)。 - 插入数据后添加
await db.commit(),保证数据写入数据库。 - 修正表结构中
guild字段的类型为INTEGER,符合Discord ID的类型规范。 - 增加私信场景处理,避免因
message.guild为None导致的报错。 - 移除冗余的
UPDATE操作,并为所有异步数据库操作添加await。 - 异常分支添加错误打印,方便排查问题。
内容的提问来源于stack exchange,提问作者Mahdiyar
相关产品推荐
相关产品推荐

