You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord工单机器人开发触发TypeError: 'int'类型不可迭代报错

问题描述

开发Discord机器人工单系统时,机器人触发反应添加事件、尝试创建支持频道的流程中抛出运行时异常,报错信息如下:

Ignoring exception in on_raw_reaction_add
Traceback (most recent call last):
  File "/home/container/.local/lib/python3.7/site-packages/discord/client.py", line 343, in _run_event
    await coro(*args, **kwargs)
  File "/home/container/cogs/ticket.py", line 67, in on_raw_reaction_add
    if user_channel_id in items:
TypeError: argument of type 'int' is not iterable

触发报错的对应原始代码:

@commands.Cog.listener()
    async def on_raw_reaction_add(self, payload):
        if payload.member.id != self.bot.user.id:
            with open('db/data.json', 'r') as file:
                ticket_data = json.load(file)

            channel_id = list(ticket_data.values())
            user_channel_id = payload.channel_id

            for items in channel_id:
                if user_channel_id in items:
                    # Get guild and roles
                    find_guild = discord.utils.find(lambda guild: guild.id == payload.guild_id, self.bot.guilds)
                    guild_roles = discord.utils.get(find_guild.roles, name=f'{payload.member.name}')

经初步定位,错误触发在if user_channel_id in items:语句行,抛出int类型不可迭代的TypeError异常。

问题产生原因

报错核心是成员判断符in的右侧必须为可迭代对象(列表、元组、集合、字符串等支持遍历的结构),但代码循环中拿到的items是整数(int)类型,不支持遍历,因此触发类型错误。
具体触发逻辑:

  1. 读取db/data.json得到字典结构的ticket_data,通过list(ticket_data.values())取出字典所有值存入channel_id列表
  2. 遍历channel_id时,代码默认每个元素都是存储了多个频道ID的可迭代结构,但实际json存储中,部分/全部值是单个整数类型的频道ID
  3. 执行if user_channel_id in items:时,Python会尝试遍历items判断目标值是否存在,发现items是无法遍历的整数,直接抛出TypeError异常。
修复方案

先确认db/data.json的实际存储结构,对应选择修复方式:

  • 如果json存储结构为「标识键: 单个工单频道ID」,例如{"ticket_owner_123": 987654321, "ticket_owner_456": 123456789},值本身就是单个整数频道ID,不需要做循环内的in判断,直接判断频道ID是否存在于值集合即可,修复后对应代码段:
@commands.Cog.listener()
async def on_raw_reaction_add(self, payload):
    if payload.member.id != self.bot.user.id:
        with open('db/data.json', 'r') as file:
            ticket_data = json.load(file)

        user_channel_id = payload.channel_id
        # 直接判断当前反应触发频道是否是已登记的工单频道
        if user_channel_id in ticket_data.values():
            find_guild = discord.utils.find(lambda guild: guild.id == payload.guild_id, self.bot.guilds)
            guild_roles = discord.utils.get(find_guild.roles, name=f'{payload.member.name}')
            # 保留原有后续业务逻辑
  • 如果json存储结构混合了单频道ID、频道ID列表两种值格式(例如部分键对应单个频道ID,部分键对应分类下的多个频道ID列表),需要在判断前先校验值的类型,避免碰到整数类型直接抛错,修复后对应代码段:
@commands.Cog.listener()
async def on_raw_reaction_add(self, payload):
    if payload.member.id != self.bot.user.id:
        with open('db/data.json', 'r') as file:
            ticket_data = json.load(file)

        user_channel_id = payload.channel_id
        all_channel_config = list(ticket_data.values())
        is_ticket_channel = False

        for item in all_channel_config:
            # 值为列表时做包含判断
            if isinstance(item, list):
                if user_channel_id in item:
                    is_ticket_channel = True
                    break
            # 值为整数时直接做相等判断
            elif isinstance(item, int):
                if user_channel_id == item:
                    is_ticket_channel = True
                    break
        
        if is_ticket_channel:
            find_guild = discord.utils.find(lambda guild: guild.id == payload.guild_id, self.bot.guilds)
            guild_roles = discord.utils.get(find_guild.roles, name=f'{payload.member.name}')
            # 保留原有后续业务逻辑

额外提示:循环变量不要命名为items,这个命名和Python字典内置的dict.items()方法重名,很容易在写逻辑时混淆变量含义,建议命名为item这类语义清晰的单数字段名。

内容的提问来源于stack exchange,提问作者Goobie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 23:57:17