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

Discord.py抽奖系统报错:async_generator无flatten属性,无法提及获奖者

Discord.py Cogs抽奖系统报错解决

问题描述

我是Discord.py新手,正在使用cogs开发抽奖系统。该系统需要机器人为抽奖消息添加反应,结束后根据点击反应的用户抽取获奖者,但抽奖结束时出现错误。

原代码

@commands.command()
@commands.has_permissions(administrator=True)
async def giveaway(self, ctx: commands.Context):
    await ctx.send("Let's start with this giveaway! Answer these questions within 15 seconds!")

    questions = ["Which channel should it be hosted in?", 
                "What should be the duration of the giveaway? (s|m|h|d)",
                "What is the prize of the giveaway?"]
    answers = []
    def check(m):
        return m.author == ctx.author and m.channel == ctx.channel 
    for i in questions:
        await ctx.send(i)
        try:
            msg = await self.bot.wait_for('message', timeout=15.0, check=check)
        except asyncio.TimeoutError:
            await ctx.send('You didn\'t answer in time, please be quicker next time!')
            return
        else:
            answers.append(msg.content)
    try:
        c_id = int(answers[0][2:-1])
    except:
        await ctx.send(f"You didn't mention a channel properly. Do it like this {ctx.channel.mention} next time.")
        return
    channel = self.bot.get_channel(c_id)
    time = convert(answers[1])
    if time == -1:
        await ctx.send(f"You didn't answer the time with a proper unit. Use (s|m|h|d) next time!")
        return
    elif time == -2:
        await ctx.send(f"The time must be an integer. Please enter an integer next time")
        return            
    prize = answers[2]
    await ctx.send(f"The Giveaway will be in {channel.mention} and will last {answers[1]}!")
    embed = discord.Embed(title = "Giveaway!", description = f"{prize}", color = ctx.author.color)
    embed.add_field(name = "Hosted by:", value = ctx.author.mention)
    embed.set_footer(text = f"Ends {answers[1]} from now!")
    my_msg = await channel.send(embed = embed)
    await my_msg.add_reaction("🎉")
    await asyncio.sleep(time)
    new_msg = await channel.fetch_message(my_msg.id)
    users = await new_msg.reactions[0].users().flatten()
    users.pop(users.index(self.bot.user))

    winner = random.choice(users)

    await channel.send(f"Congratulations! {winner.mention} won {prize}!")

def convert(time):
        pos = ["s","m","h","d"]

        time_dict = {"s" : 1, "m" : 60, "h" : 3600 , "d" : 3600*24}

        unit = time[-1]

        if unit not in pos:
            return -1
        try:
            val = int(time[:-1])
        except:
            return -2


        return val * time_dict[unit]

报错信息

Traceback (most recent call last):
  File "C:\Users\Human\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\core.py", line 229, in wrapped
    ret = await coro(*args, **kwargs)
  File "c:\Users\Human\Documents\TestBot\cogs\giveaways.py", line 78, in giveaway
    users = await new_msg.reactions[0].users().flatten()
AttributeError: 'async_generator' object has no attribute 'flatten'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\Human\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\bot.py", line 1349, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\Human\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\core.py", line 1023, in invoke
    await injected(*ctx.args, **ctx.kwargs)  # type: ignore
  File "C:\Users\Human\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\core.py", line 238, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'async_generator' object has no attribute 'flatten'

报错原因

Discord.py v2.x版本对API进行了更新,Reaction.users()方法不再返回可迭代的用户集合,而是返回异步生成器,因此原来调用的.flatten()方法不再存在,导致报错。

解决办法

修改获取反应用户的代码,通过异步遍历生成器来收集用户,同时过滤掉机器人自身:

替换代码段

将原代码中的:

users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(self.bot.user))

替换为以下两种写法之一:

写法一:异步循环收集

users = []
async for user in new_msg.reactions[0].users():
    if user != self.bot.user:
        users.append(user)

写法二:异步列表推导式(更简洁)

users = [user async for user in new_msg.reactions[0].users() if user != self.bot.user]

额外优化

为了避免没有用户参与抽奖时random.choice()报错,可以添加判断逻辑:

if not users:
    await channel.send("没有用户参与本次抽奖,无法选出获奖者!")
    return
winner = random.choice(users)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:25:20