【问题标题】:Running a function blocks the bot - discord.py运行一个函数会阻止机器人 - discord.py
【发布时间】:2021-12-27 20:30:46
【问题描述】:

我试图使用在 discord 上键入的命令从四个文件(它们有 4GB 大)中搜索数据。 搜索功能的执行时间大约需要十分钟,遍历4个文件;当我尝试连续输入两次命令时,第二个命令在第一个命令执行后执行(大约 10 分钟后)。

def main(self):
    @self.client.command()
    async def fsearch(ctx, *args):
        self.client.loop.create_task(self.searchTask(ctx, *args)) 

self.searchTask是搜索功能。

有什么想法可以让函数在不阻塞机器人的情况下执行吗? (一段时间后,机器人在执行过程中下线。)

更新:

这是来自self.searchTask函数的代码sn-p:

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")

【问题讨论】:

    标签: python discord discord.py python-asyncio


    【解决方案1】:

    您不能在异步代码中使用阻塞函数。似乎searchTask 正在阻塞,因此您的事件循环正在停止。 Asyncio 事件循环提供了一个简单的API 用于在线程池或进程池中运行阻塞函数,以防止它们阻塞您的事件循环。

    编辑:示例:在线程中运行文件操作

    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")
    

    【讨论】:

    • self.searchTask 不是同步函数,是异步函数。
    • 你能贴出它的代码吗?
    • 完成,代码更新。
    • @ClownDown 好吧,代码仍然不完整,所以这很难确定,但我仍然相信searchTask 正在阻塞。您的代码不会自动异步工作,因为您使用async def 声明了它。只有当您的代码将控制权返回给循环时,事件循环才能退出您的代码,例如await。如果两个awaits 之间有大量计算,那么您的事件循环会在这段时间内被阻塞。
    • 你可以,如果你重构出阻塞位。我将尝试使用基于您的代码的示例来更新我的答案。
    猜你喜欢
    • 2023-03-15
    • 2019-06-17
    • 2021-01-29
    • 1970-01-01
    • 2012-08-13
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多