I've created a few bots using the discord.py library and I now want to build a 'dispatcher' that reads a configuration file and launches them all. Each of my bots is created as a class extending from an abstract bot class. However, I'm stuck at running them simultaneously. These are some things I've tried:
threading.Thread(target=discord.Client('token').run)).start()
. Doesn't work because Client.run()
tries to start the asyncio
event loop again, causing an error (RuntimeError: Cannot close a running event loop
).os.system
/multiprocessing
/subprocess
. To run .py
files containing bots. Doesn't work because os.system
etc blocks until the subprocess has ended (ie the bot is killed). I'd also prefer not to use this method because it's a biasyncio
loop (shown below).MRE of the last method I tried:
import discord
import asyncio
class Bot:
client = discord.Client()
def __init__(self, token):
self.token = token
print('Bot initiated')
@self.client.event
async def on_ready():
print(f'Logged in as {self.client.user}')
@self.client.event
async def on_message(message):
print(message.content)
async def run(self):
print('Bot running')
self.client.run(self.token)
if __name__ == '__main__':
bot1 = Bot('bot token here')
bot2 = Bot('bot token here')
loop = asyncio.get_event_loop()
loop.create_task(bot1.run())
loop.create_task(bot2.run())
loop.run_forever()
This doesn't work at all - the first bot freezes in the run
method and never even logs in. For testing, both bots were logging into the same bot account but that's irrelevant to the problem.
I presume that the ideal solution would be a way to asynchronously run a discord.Client
, but I haven't come across any way to do this.
Easiest approach would be using subprocess.Popen
import sys
import subprocess
files = ["bot1.py", "bot2.py", ...]
for f in files:
subprocess.Popen(
[sys.executable, f], stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
It will start all the files in the background.