discord.py 2.1.0获取频道最后一条消息的问题及报错排查
Discord.py 2.1.0 获取频道最后一条消息问题解决
问题场景
使用discord.py 2.1.0时,想要获取服务器内指定前缀频道的最后一条消息,尝试两段代码后遇到以下问题:
第一段代码及问题
代码:
@tree.command(guild = discord.Object(id=941748573937209344), name = 'kontrol', description='kontrol') async def check(ctx): channels = ctx.guild.text_channels for channel in channels: if channel.name.startswith('test-'): last_message = [msg async for msg in channel.history(limit=1)] print(last_message)
输出结果:
[<Message id=1060085926157619221 channel=<TextChannel id=1060078850417111112 name='test-supraaaaaa' position=19 nsfw=False news=False category_id=941749835328012328> type=<MessageType.default: 0> author=<User id=323516141777715202 name='supraaaaaa' discriminator='0966' bot=False> flags=<MessageFlags value=0>>]
问题:输出中无法看到消息的创建时间。
第二段代码及报错
代码:
@tree.command(guild = discord.Object(id=941748573937209344), name = 'kontrol', description='kontrol') #guild specific slash command async def check(ctx): channels = ctx.guild.text_channels for channel in channels: if channel.name.startswith('övgü-'): last_message = [msg async for msg in channel.history(limit=1)] print(last_message.id)
报错信息:
AttributeError: 'list' object has no attribute 'id'
错误原因
- 列表对象导致属性访问错误:
channel.history(limit=1)返回异步迭代器,用列表推导式转成的是包含单个Message对象的列表,而非单个Message实例,直接访问.id会触发属性错误。 - 默认打印未展示创建时间:Message对象默认打印时不会输出
created_at属性,需要主动访问才能获取该信息。
修正后的代码
方式一:通过异步循环取出消息
@tree.command(guild = discord.Object(id=941748573937209344), name = 'kontrol', description='kontrol') async def check(ctx): channels = ctx.guild.text_channels for channel in channels: # 匹配目标频道前缀 if channel.name.startswith('test-') or channel.name.startswith('övgü-'): last_message = None # 从异步迭代器中取出最后一条消息 async for msg in channel.history(limit=1): last_message = msg break if not last_message: print(f"频道 {channel.name} 无消息") continue # 输出消息详情 print(f"频道 {channel.name} 最后一条消息:") print(f"消息ID: {last_message.id}") print(f"创建时间: {last_message.created_at}") # 可选:输出消息内容 # print(f"消息内容: {last_message.content}")
方式二:使用anext()直接获取消息(更简洁)
@tree.command(guild = discord.Object(id=941748573937209344), name = 'kontrol', description='kontrol') async def check(ctx): channels = ctx.guild.text_channels for channel in channels: if channel.name.startswith('test-') or channel.name.startswith('övgü-'): try: # 从异步迭代器中获取第一条(即最后一条)消息 last_message = await anext(channel.history(limit=1)) except StopAsyncIteration: print(f"频道 {channel.name} 无消息") continue print(f"频道 {channel.name} 最后一条消息:") print(f"消息ID: {last_message.id}") print(f"创建时间: {last_message.created_at}")
关键点说明
- 避免将异步迭代器转为列表,直接获取单个Message实例才能访问其属性(如
.id、.created_at)。 - Message对象的
created_at属性存储了消息的创建时间,需主动调用才能展示。 - 加入无消息场景的处理,避免程序抛出异常。
内容的提问来源于stack exchange,提问作者ahmet güzel
相关产品推荐
相关产品推荐

