为啥我会收到这个 TypeError?
Posted
技术标签:
【中文标题】为啥我会收到这个 TypeError?【英文标题】:Why I`m getting this TypeError?为什么我会收到这个 TypeError? 【发布时间】:2022-01-23 22:23:40 【问题描述】:我正在尝试创建一个 getprefix 命令,它会更改服务器前缀。我正在使用 sql 数据库来存储前缀。当我在服务器中发送任何消息时,我收到以下错误,而不仅仅是机器人命令:
Traceback (most recent call last):
File "C:\Users\tudor\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\bot.py", line 835, in get_prefix
ret = list(ret)
TypeError: 'NoneType' object is not iterable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\tudor\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "C:\Users\tudor\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\bot.py", line 979, in on_message
await self.process_commands(message)
File "C:\Users\tudor\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\bot.py", line 975, in process_commands
ctx = await self.get_context(message)
File "C:\Users\tudor\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\bot.py", line 886, in get_context
prefix = await self.get_prefix(message)
File "C:\Users\tudor\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\bot.py", line 842, in get_prefix
raise TypeError("command_prefix must be plain string, iterable of strings, or callable "
TypeError: command_prefix must be plain string, iterable of strings, or callable returning either of these, not NoneType
我的代码:
def get_prefix(bot, message):
prefix = db.field("SELECT Prefix FROM guilds WHERE GuildID = ?", message.guild.id)
return when_mentioned_or(prefix)(bot, message)
我的数据库代码:
from os.path import isfile
from sqlite3 import connect
from apscheduler.triggers.cron import CronTrigger
DB_PATH = "./data/db/database.db"
BUILD_PATH = "./data/db/build.sql"
cxn = connect(DB_PATH, check_same_thread=False)
cur = cxn.cursor()
def with_commit(func):
def inner(*args, **kwargs):
func(*args, **kwargs)
commit()
return inner
@with_commit
def build():
if isfile(BUILD_PATH):
scriptexec(BUILD_PATH)
def commit():
cxn.commit()
def autosave(sched):
sched.add_job(commit, CronTrigger(second=0))
def close():
cxn.close()
def field(command, *values):
cur.execute(command, tuple(values))
if (fetch := cur.fetchone()) is not None:
return fetch[0]
def record(command, *values):
cur.execute(command, tuple(values))
return cur.fetchone()
def records(command, *values):
cur.execute(command, tuple(values))
return cur.fetchall()
def column(command, *values):
cur.execute(command, tuple(values))
return [item[0] for item in cur.fetchall()]
def execute(command, *values):
cur.execute(command, tuple(values))
def multiexec(command, valueset):
cur.executemany(command, valueset)
def scriptexec(path):
with open(path, "r", encoding="utf-8") as script:
cur.executescript(script.read())
我第一次尝试这个时,它使用相同的代码完美地工作:我能够更新数据库中服务器的自定义前缀而没有任何错误。
【问题讨论】:
你在哪里定义ret
?
【参考方案1】:
由于 fetch 变量为 None,所以抛出异常,因为 cur.fetchone() 返回 None(没有从数据库中检索到数据),因此该函数跳过 if 并返回 None
def field(command, *values):
cur.execute(command, tuple(values))
if (fetch := cur.fetchone()) is not None:
return fetch[0]
等价于
def field(command, *values):
cur.execute(command, tuple(values))
if (fetch := cur.fetchone()) is not None:
return fetch[0]
else:
return None # Causing the error
我认为它可能来自tuple(values)
,变量value
实际上已经是一个元组,如您在此示例中所见,表明您不需要在参数上调用tuple()
。尝试不使用元组它可能会工作
>>> def foo(*a):
... print(tuple(a))
...
>>> foo(5,6)
(5, 6)
>>>
>>> def bar(*a):
... print(a)
...
>>> bar(5,6)
(5, 6)
>>>
【讨论】:
我试过了,没有任何改变.. 那么问题可能是您的数据库没有任何与查询匹配的数据。您也可以尝试在查询字符串中使用%s
而不是?
或者最后您可以尝试将message.guild.id 包装在一个元组中,例如... = ?", tuple(message.guild.id)
或... = ?", (message.guild.id, ) )
(逗号不是错字)
sqlite3.OperationalError: near "%": syntax error
最后一个解决方案我得到了这个:prefix = db.field("SELECT Prefix FROM guilds WHERE GuildID = %s", tuple(message.guild.id)) TypeError: 'int' object is not iterable
那么忘记 %s 吧,元组 (message.guild.id) 也是如此,它必须依赖于您的 SQL 库。那么我的回答对你没有帮助:/以上是关于为啥我会收到这个 TypeError?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我收到 TypeError: Failed to fetch?