Как запустить бота с использованием библиотек discord.py и asyncio?

Добрый день! Я планирую запустить бота асинхронно и хотел бы получить рекомендации по устранению проблемы. Как можно исправить следующую ошибку? <br/> <code>Task exception was never retrieved</code> <br/> <br/> Ниже представлена структура файлов: <br/> <b>bot.py</b> <br/> <pre><code class="python">from test import Test

token = ""
redis_url = "redis://"
mongo_url = "mongodb://"

bot = Test(redis_url=redis_url, mongo_url=mongo_url)
bot.run(token)</code></pre> <br/> <br/> <b>test.py</b> <br/> <pre><code class="python">import discord
from database import Db
import asyncio

class Test(discord.Client):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs, intents=discord.Intents.all())
        self.redis_url = kwargs.get('redis_url')
        self.mongo_url = kwargs.get('mongo_url')
        self.loop = asyncio.get_event_loop()

    def run(self, *args):
        self.loop.run_until_complete(self.start(*args))

    async def on_ready(self):
        print('hello!')</code></pre>
  • 13 апреля 2025 г. 10:55
Ответы на вопрос 2
Ошибка `Task exception was never retrieved` в вашем коде может возникать, когда в асинхронной функции возникает исключение, и оно не обрабатывается. Давайте разберемся, как можно улучшить вашу структуру кода и решить эту проблему.

### Основные изменения

1. **Обработка исключений:** Добавьте обработку исключений в ваши асинхронные функции, чтобы иметь возможность видеть ошибки, если они возникают.

2. **Правильное использование `asyncio`:** Вместо того, чтобы использовать `self.loop.run_until_complete()`, будет лучше вызвать `await self.start()` внутри асинхронного метода. Переименуем метод `run` в `start` и вызовем его в основной функции.

### Исправленный код

**bot.py:**
```python
from test import Test

token = ""
redis_url = "redis://"
mongo_url = "mongodb://"

bot = Test(redis_url=redis_url, mongo_url=mongo_url)

# Запуск бота
if __name__ == "__main__":
    try:
        # Запускаем бота асинхронно
        bot.run(token)
    except Exception as e:
        print(f"Error: {e}")
```

**test.py:**
```python
import discord

class Test(discord.Client):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs, intents=discord.Intents.all())
        self.redis_url = kwargs.get('redis_url')
        self.mongo_url = kwargs.get('mongo_url')

    async def on_ready(self):
        print('Bot is online!')
```

Теперь напрямую вызываем `bot.run(token)` для запуска бота, и это будет правильно обрабатывать оба запуска и события, такие как `on_ready`.

### Дополнительные рекомендации

- Убедитесь, что вы используете актуальную версию `discord.py`, поддерживающую вашу версию Python.
- Убедитесь, что ваши `token`, `redis_url`, и `mongo_url` корректны и надежны.
- Вы можете также включить обработку исключений в методах `on_ready` и других асинхронных методах для лучшего отслеживания ошибок.

### Еще одно замечание

Если у вас включен `-W error` в интерпретаторе Python, это может приводить к исключениям, которые игнорируются. Убедитесь, что вы тестируете в среде, где обработка исключений настроена правильно, чтобы видеть все ключевые ошибки, которые могут возникнуть.

Надеюсь, это поможет вам! Если возникнут дополнительные вопросы, не стесняйтесь спрашивать.
Как можно запустить бота на discord py и asyncio
Так, как описано в документации библиотеки. Внутри функции run уже есть логика инициализации цикла событий
import discord

intents = discord.Intents.default()
intents.message_content = True

client = discord.Client(intents=intents)
client.run('your token here')


Если вы хотите самостоятельно им управлять есть функция start() , но в вашем варианте вы не получаете вообще никаких преимуществ, следовательно, все это не нужно. Обычно так делают если хотят вызывать бота в уже существующем цикле событий (и потом страдать). Для этого нужен asyncio.create_task(bot.start(token=token)

Подробно с комментариями бот в виде кастомного класса описан тут .

Task exception was never retrieved

Цикл событий завершается с исключением, которое вы не обрабатываете. А исключение вызывается, потому что start не принимает то, что вы пытаетесь в него передать *args

P.S. лучше описывать какую проблему вы решаете, а не что пытаетесь сделать.
Похожие вопросы