TypeError: object async_generator can't be used in 'await' expression
Выводит следующую ошибку в терминале:
discord.ext.commands.bot Ignoring exception in command punishments
Traceback (most recent call last):
File "/home/runner/GlaringSteepArchives/venv/lib/python3.10/site-packages/discord/ext/commands/core.py", line 229, in wrapped
ret = await coro(*args, **kwargs)
File "main.py", line 110, in punishments
bans = await ctx.guild.bans()
TypeError: object async_generator can't be used in 'await' expression
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/runner/GlaringSteepArchives/venv/lib/python3.10/site-packages/discord/ext/commands/bot.py", line 1350, in invoke
await ctx.command.invoke(ctx)
File "/home/runner/GlaringSteepArchives/venv/lib/python3.10/site-packages/discord/ext/commands/core.py", line 1023, in invoke
await injected(*ctx.args, **ctx.kwargs) # type: ignore
File "/home/runner/GlaringSteepArchives/venv/lib/python3.10/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: TypeError: object async_generator can't be used in 'await' expression
Сам код:
@bot.command()
async def punishments(ctx, member: discord.Member):
# Получаем список банов на сервере
bans = await ctx.guild.bans()
# Получаем список киков с сервера
kicks = await ctx.guild.audit_logs(limit=100, action=discord.AuditLogAction.kick).flatten()
# Получаем список мутов с сервера
mutes = await ctx.guild.audit_logs(limit=100, action=discord.AuditLogAction.mute).flatten()
# Списки наказаний для пользователя
user_bans = [ban for ban in bans if ban.user == member]
user_kicks = [kick for kick in kicks if kick.target == member]
user_mutes = [mute for mute in mutes if mute.target == member]
# Список всех наказаний
punishment_list = []
# Добавляем в список все баны пользователя
for ban in user_bans:
punishment_list.append(f'Banned on {ban.created_at.strftime("%Y-%m-%d %H:%M:%S")}')
# Добавляем в список все кики пользователя
for kick in user_kicks:
punishment_list.append(f'Kicked on {kick.created_at.strftime("%Y-%m-%d %H:%M:%S")}')
# Добавляем в список все муты пользователя
for mute in user_mutes:
punishment_list.append(f'Muted on {mute.created_at.strftime("%Y-%m-%d %H:%M:%S")}')
# Если у пользователя нет наказаний, то сообщаем об этом
if len(punishment_list) == 0:
await ctx.send(f'{member} has no punishments.')
# Иначе отображаем все наказания
else:
# Сортируем список по дате создания
punishment_list.sort()
# Преобразуем список в строку и отправляем на сервер
await ctx.send(f'{member} punishments:\n' + '\n'.join(punishment_list))
Ответы (1 шт):
Автор решения: insolor
→ Ссылка
Ошибка
bans = await ctx.guild.bans()
TypeError: object async_generator can't be used in 'await' expression
говорит, что метод .bans() - это асинхронный генератор, и его нельзя использовать вместе с конструкцией await.
Для работы с асинхронными генераторами (в целом - с асинхронными итераторами или итерируемыми объектами) нужно использовать async for.
В данном случае, чтобы получить элементы из асинхронного генератора можно использовать такую конструкцию:
bans = [ban async for ban in ctx.guild.bans()]
Минимальный пример с демонстрацией:
import asyncio
async def get_bans():
"""Пример асинхронного генератора"""
for ban in range(10):
await asyncio.sleep(0.1)
yield ban
async def main():
# bans = await get_bans() выдаст ошибку TypeError: object async_generator can't be used in 'await' expression
bans = [ban async for ban in get_bans()]
print(bans)
# Вывод: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
if __name__ == "__main__":
asyncio.run(main())
Еще вариант - использовать aiostream.stream.list из модуля aiostream (pip install aiostream):
bans = await stream.list(ctx.guild.bans())
Ссылки:
- PEP 525 - про асинхронные генераторы
- PEP 492 / Asynchronous Iterators and “async for” - про асинхронные итераторы и
async for - Документация aiostream