Issue
I was trying to search data from four files (they're 4GB large) using a command typed on discord. The execution time of the search function takes about ten minutes to iterate through the 4 files; when I tried to type the command twice in a row, the second command get executed after the first command get executed (about 10 minutes later).
def main(self):
@self.client.command()
async def fsearch(ctx, *args):
self.client.loop.create_task(self.searchTask(ctx, *args))
self.searchTask
is the searching function.
Is there any idea to let the function execute without blocking the bot? (after a while the bot goes offline during the execution.)
Update:
This is a code snippet from the self.searchTask
function:
async def searchTask(self, ctx, *args):
found = False
name = args[0].lower().
surname = args[1].lower()
await ctx.send("Searching data...")
with open(f"{CURRENT_DIR}/out.txt", "w") as fwrite:
flist = os.listdir(f"{CURRENT_DIR}/datab")
for x in flist:
with open(f"{CURRENT_DIR}/datab/{x}", "rb") as f:
for line in f:
...
fwrite.close()
if found:
await ctx.send("Done! Here's the result:")
await ctx.send(file=discord.File(f"{CURRENT_DIR}/out.txt"))
else:
await ctx.send("Can't find data")
Solution
You cannot have blocking functions in asynchronous code. It seems searchTask
is blocking and so your event loop is grinding to a halt. Asyncio event loops provide a simple API for running blocking functions in a threadpool or processpool to keep them from blocking your event loop.
EDIT: Example: Run file operations in thread
def search_files():
found = False
flist = os.listdir(f"{CURRENT_DIR}/datab")
for x in flist:
with open(f"{CURRENT_DIR}/datab/{x}", "rb") as f:
for line in f:
found = found or is_found(line) # check your condition in is_found
return found
async def searchTask(self, ctx, *args):
name = args[0].lower()
surname = args[1].lower()
await ctx.send("Searching data...")
loop = asyncio.get_running_loop()
with open(f"{CURRENT_DIR}/out.txt", "w") as fwrite:
found = await loop.run_in_executor(None, search_files)
# write something to fwrite
# also do this in executor if it's a lot
fwrite.close() # this is unnecessary if you as using 'with'
if found:
await ctx.send("Done! Here's the result:")
await ctx.send(file=discord.File(f"{CURRENT_DIR}/out.txt"))
else:
await ctx.send("Can't find data")
Answered By - thisisalsomypassword
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.