Logicman
Logicman

Reputation: 129

Python asyncio/discord.py - Loop exits with Task was destroyed but it is pending

The relevant code pertaining to my issue:

discordbot.py

import discord, main, websockets
from discord.ext import commands

TOKEN = ''

description = '''Description'''
bot = commands.Bot(command_prefix='!', description=description)

@bot.event
async def on_ready():
    print('----------------------------')
    print('Connected!')
    print('Logged in as: {0}'.format(bot.user.name))
    print('Bot ID: {0}'.format(bot.user.id))
    print('----------------------------')


@bot.command()
async def wall(coin, desired_multiplier):
    try:
        desired_multiplier = float(desired_multiplier)
    except:
        await bot.say("That's not a percent!")
    desired_multiplier = float("{0:.1f}".format(desired_multiplier))
    try:
        if desired_multiplier <= 2.0:
            #await bot.say('Calculating...')
            volume, rate, last_price = main.get_sells(coin, desired_multiplier)
            total_btc = sum(volume)
            total_btc = float("{0:.3f}".format(total_btc))
            await bot.say('Success')
            print('Total of {0} BTC to reach a {1}x multiplier for {2}'.format(total_btc, desired_multiplier, coin.upper()))
        else:
            await bot.say('Please use a multiplier under 2x, apparently I can\'t handle more than that.')
    except:
        await bot.say('Error: Please make sure the coin is registered on Bittrex!')

bot.run(TOKEN)

main.py

from bittrex import Bittrex
import requests

bittrex = Bittrex('', '')
BUY_ORDERBOOK = 'buy'
SELL_ORDERBOOK = 'sell'
BOTH_ORDERBOOK = 'both'

def total_btc(quantity, rate):
    total = rate * quantity
    return total

def get_sells(coin, desired_multiplier):
    volume = []
    sells = bittrex.get_orderbook('BTC-{0}'.format(coin), SELL_ORDERBOOK)
    if sells['success'] is False:
        print(sells['message'], '#########################################################')
    for sell in range(10000):
        order = sells['result'][sell]
        quantity = order['Quantity']
        rate = order['Rate']
        total = total_btc(quantity, rate)
        volume.append(total)
        last_price = bittrex.get_ticker('BTC-{0}'.format(coin))['result']['Last']
        multiplier = rate / last_price
        multiplier = float("{0:.1f}".format(multiplier))
        print('{0} | {1}'.format(sell, multiplier))
        if multiplier != desired_multiplier:
            continue
        else:
            return volume, rate, last_price

The error and traceback:

Task was destroyed but it is pending!
task: <Task pending coro=<Client._run_event() running at C:\Users\logicmn\D
ocuments\discordenv\lib\site-packages\discord\client.py:307> wait_for=<Future pe
nding cb=[BaseSelectorEventLoop._sock_connect_done(704)(), <TaskWakeupMethWrappe
r object at 0x0000000003CE2258>()]>>
Exception ignored in: <generator object Bot.on_message at 0x0000000003CDC048>
Traceback (most recent call last):
  File "C:\Users\logicmn\Documents\discordenv\lib\site-packages\discord\ext
\commands\bot.py", line 857, in on_message
    yield from self.process_commands(message)
  File "C:\Users\logicmn\Documents\discordenv\lib\site-packages\discord\ext
\commands\bot.py", line 848, in process_commands
    ctx.command.dispatch_error(e, ctx)
  File "C:\Users\logicmn\Documents\discordenv\lib\site-packages\discord\ext
\commands\core.py", line 164, in dispatch_error
    ctx.bot.dispatch('command_error', error, ctx)
  File "C:\Users\logicmn\Documents\discordenv\lib\site-packages\discord\ext
\commands\bot.py", line 262, in dispatch
    super().dispatch(event_name, *args, **kwargs)
  File "C:\Users\logicmn\Documents\discordenv\lib\site-packages\discord\cli
ent.py", line 325, in dispatch
    compat.create_task(self._run_event(method, *args, **kwargs), loop=self.loop)

  File "c:\users\logicmn\appdata\local\continuum\anaconda3\Lib\asyncio\task
s.py", line 512, in ensure_future
    task = loop.create_task(coro_or_future)
  File "c:\users\logicmn\appdata\local\continuum\anaconda3\Lib\asyncio\base
_events.py", line 282, in create_task
    self._check_closed()
  File "c:\users\logicmn\appdata\local\continuum\anaconda3\Lib\asyncio\base
_events.py", line 357, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

This seems relevant but I attempted the solution and couldn't get it to work. I do believe the issue is because the discord client module needs control once every ~60 seconds. Since my function get_sells() takes more like ~70 seconds, asyncio breaks.

Upvotes: 0

Views: 1592

Answers (1)

Arthur
Arthur

Reputation: 4241

the discord client apparently needs control every minute or so, and your get_sells function is blocking for more than that.

This is because you are mixing a synchronous bittrex client, with an asyncio library (discord). You will need to use the same paradigm for both: the discord client is based on asyncio, so you will need to find an asyncio-based library for bittrex (or write one).

This new library should expose some coroutine similar to the functions you are using. So you would call sells = await bittrex_aio.get_orderbook(…), instead of sells = bittrex.get_orderbook(…) and def get_sells(…) would become a coroutine async def get_sells(…).

With this, you will be able to change your bot to use await main.get_sells, which means the discord client will be able to take control while you are waiting for the results of get_sells.

I am not getting into the specific of asyncio here on purpose, but reading about it would probably help, here for instance: https://docs.python.org/3/library/asyncio.html

Upvotes: 1

Related Questions