-2

Im using the discord.py library and im developing a discord bot.

Basically, i need my bot to go to a website every hour and get some info with selenium. I want to do it in a thread to avoid blocking the bot during the info gathering.

@tasks.loop(hours=1)
async def getwebsiteinfo(self):
    thr = threading.Thread(target=self.getwebsiteinfofunc)
    thr.start()

getwebsiteinfofunc:

def getwebsiteinfofunc(self):
...
channel.send(f"```sometext```")
..

Here is the problem: channel.send needs to be called with await but i cant call it with await because its not inside an async function.

But i cant either define getwebsiteinfofunc as async because i cant use async functions with threads.

I tried asyncio but i never used it and i failed.

Any ideas?

Ivan Ambla
  • 763
  • 5
  • 24
  • See [here](https://stackoverflow.com/a/53597795/9083371). – Benjin Sep 22 '20 at 15:35
  • i cant use the loop.run_in_executor because where am i suppused to call it? if i call it in the init of my class its not async – Ivan Ambla Sep 22 '20 at 15:52
  • keep in mind that i need it to run in a loop its not a one time command that wait for an amount of time – Ivan Ambla Sep 22 '20 at 15:54
  • instead of `thr = threading.Thread(target=self.getwebsiteinfofunc)` you can use `result = await loop.run_in_executor(ThreadPoolExecutor(), self.getwebsiteinfofunc)` inside an async function. You can then call `await channel.send(result)` in the async function. If you want specific code for these, please update your question with a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) (code that can run as is, not just snippets). – Benjin Sep 22 '20 at 19:20

1 Answers1

0

If you write your whole task in async it will not block the rest of the bot, asyncio itself allows you to write concurrent tasks without needing threading.

There are aio alternatives for many sync libraries, for example, use the aiohttp Client in place of the requests library.

unex
  • 1,356
  • 1
  • 8
  • 14
  • my whole task is already in async (i used @tasks.loop and an asyn definiton) but it blocks the bot, i tested it trying to send another command while the task was sunning and the bot didnt responded until the task was finished. im a beginner so i dont know how to start a task from a non async function – Ivan Ambla Sep 22 '20 at 16:23
  • You have something in your task that is doing a synchronous operation, continuing from my example above, if you use `requests` in your task it will block the event loop until it completes. – unex Sep 22 '20 at 16:33
  • i use selenium, thats why i used a thread in the first place, is there a way to solve this still using selenium? – Ivan Ambla Sep 22 '20 at 16:41
  • The closest I can find at a quick glance is https://github.com/HDE/arsenic. You could also try using [run_in_executor](https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor) to run your blocking selenium operations – unex Sep 22 '20 at 17:37