0

I have a background loop involving selenium, so it takes a long time to finish executing. I noticed that the bot had a delay when responding to commands, and I found out that the processes inside @tasks.loop() needs to finish before the commands execute. For example:

from discord.ext import commands, tasks
import time

bot = commands.Bot(command_prefix='-')

@bot.command()
async def test(ctx):
    await ctx.send('hi')

@tasks.loop(seconds=30)
async def loop():
    print('h')
    time.sleep(20)
    print('i')


@bot.event
async def on_ready():
    loop.start()

bot.run()

Here, if you do -test after it prints the letter h and before it prints the letter i, the bot will not respond until it prints the i and the loop finishes.

How would I make it so that the commands will be able to execute along with the loop? FYI my code doesn't have a time.sleep(), it was just an example.

F.M
  • 935
  • 13
  • 28
  • long-running code you have to run in separated thread. – furas May 10 '21 at 23:14
  • @furas How would I do that? – F.M May 10 '21 at 23:16
  • python has modules [threading](https://docs.python.org/3/library/threading.html) and [multiprocessing](https://docs.python.org/dev/library/multiprocessing.html) for this. You should find many tutorials for this. `t = threading.Thread(target=function_name)` and `t.start()` - so first you have to put code in new function. And later use `Thread` in `loop`. BTW: `target needs function's name without `()` - it will later use `()` to run it. – furas May 10 '21 at 23:49
  • Does this answer your question? [Python Discord.py \`time.sleep()\` coroutine](https://stackoverflow.com/questions/61147936/python-discord-py-time-sleep-coroutine) – duckboycool May 11 '21 at 21:11
  • @duckboycool No, as I said there are no `time.sleep()` in my loop – F.M May 11 '21 at 22:29

1 Answers1

1

If you have long running code then you should move it into separated function and run it with threading or `multiprocessing.

Here basic example with threading. It runs new thread in every loop. For something more complex it may need different menthod. It may need to run single thread before discord and use queue in loop to send information to thread.

from discord.ext import commands, tasks
import time
import threading
import os

bot = commands.Bot(command_prefix='-')

@bot.command()
async def test(ctx):
    await ctx.send('hi')

def long_running_function():
    print('long_running_function: start')
    time.sleep(10)
    print('long_running_function: end')
    
@tasks.loop(seconds=30)
async def loop():
    print('h')
    t = threading.Thread(target=long_running_function)
    t.start()
    print('i')

@bot.event
async def on_ready():
    loop.start()

bot.run(os.getenv('DISCORD_TOKEN'))
furas
  • 119,752
  • 10
  • 94
  • 135
  • This works very well, but I just realized I have `await` inside the loop, and when I try to run it it gives me a syntax error. How would I solve that? – F.M May 11 '21 at 14:19
  • better create new question on new page - you will have place to show current code and full error message. – furas May 11 '21 at 14:44