为啥我会收到这个 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?

为啥我会收到不支持的操作数类型错误?

当它不可能是真的时,为啥我会收到这个错误?

为啥我会收到这个语法错误(false syntax error pyflakes)

我在解析 JSON 时遇到错误。为啥我会收到这个错误?

Mocha API 测试:获取“TypeError:app.address 不是函数”