无法关闭正在运行的事件循环

时间:2021-06-12 20:13:28

标签: python python-3.x django discord.py python-asyncio

任务完成后关闭 discord.py bot 循环的方法是什么?

添加:

nest_asyncio.apply()

尝试过:

bot.logout(), bot.close(), bot.cancel()

代码:

async def helper(bot, discord_user_feed):
    nest_asyncio.apply()
    await bot.wait_until_ready()
    # await asyncio.sleep(10)
    for each_id, events_list in discord_user_feed.items():
        discord_user = await bot.fetch_user(int(each_id))
        for each_one in events_list:
            msg_sent = True
            while msg_sent:
                await discord_user.send(each_one)
                msg_sent = False
    await bot.close()
    return 'discord messages sent'


async def discord_headlines(request):
    nest_asyncio.apply()
    discord_user_feed =  await get_details()
    bot = commands.Bot(command_prefix='!')
    bot.loop.create_task(helper(bot, discord_user_feed))
    message = bot.run('my_token')
    return HttpResponse(message)

我可以使用 id 和 discord bot 向 discord 用户发送消息。但是,即使在此之后,django view api 仍在不断运行并出现错误。它需要返回响应消息 - 发送不和谐消息。

错误:

Exception in callback <TaskWakeupMethWrapper object at 0x000001C852D2DA38>(<Future finis...SWdZVtXT7E']}>)
handle: <Handle <TaskWakeupMethWrapper object at 0x000001C852D2DA38>(<Future finis...SWdZVtXT7E']}>)>
Traceback (most recent call last):
  File "E:\sd\envs\port\lib\asyncio\events.py", line 145, in _run
    self._callback(*self._args)
KeyError: <_WindowsSelectorEventLoop running=True closed=False debug=False>
Internal Server Error: /api/v0/discord_headlines/
Traceback (most recent call last):
  File "E:\sd\envs\port\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "E:\sd\envs\port\lib\site-packages\django\core\handlers\base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "E:\sd\envs\port\lib\site-packages\asgiref\sync.py", line 139, in __call__
    return call_result.result()
  File "E:\sd\envs\port\lib\concurrent\futures\_base.py", line 425, in result
    return self.__get_result()
  File "E:\sd\envs\port\lib\concurrent\futures\_base.py", line 384, in __get_result
    raise self._exception
  File "E:\sd\envs\port\lib\site-packages\asgiref\sync.py", line 204, in main_wrap
    result = await self.awaitable(*args, **kwargs)
  File "E:\back-end\port_api\views\discord_integration.py", line 110, in discord_headlines
    message = bot.run('my_token')
  File "E:\sd\envs\port\lib\site-packages\discord\client.py", line 719, in run
    _cleanup_loop(loop)
  File "E:\sd\envs\port\lib\site-packages\discord\client.py", line 95, in _cleanup_loop
    loop.close()
  File "E:\sd\envs\port\lib\asyncio\selector_events.py", line 107, in close
    raise RuntimeError("Cannot close a running event loop")
RuntimeError: Cannot close a running event loop
[13/Jun/2021 01:07:34] "GET /api/v0/discord_headlines/ HTTP/1.1" 500 109010

这些是版本:

Python 3.6.4, Django 3.1, discord.py 1.7.3, Asyncio, Anaconda-4.9.2, Windows-10

1 个答案:

答案 0 :(得分:1)

我没有使用过旧版本,所以我无法证明这个答案对于 2021 年之前的版本 (v1.6.0+) Discord.py 的准确性。

当通过 run(*args, **kwargs) 启动 Discord Client 或 Bot 时,实际上没有类方法可以阻止它。

根据 Discord.py 文档Discord.py discord.Client.run

<块引用>

一个阻塞调用,它抽象出事件循环初始化 你。

如果你想更多地控制事件循环,那么这个函数应该 不被使用。使用 start() 协程或 connect() + login()

它实际上等于:

# run(*args, **kwargs) is basically
try:
    # Start the bot on asyncio event loop with using .start() coroutine
    loop.run_until_complete(start(*args, **kwargs))
except KeyboardInterrupt:
    # Invoke close() coroutine on the same loop if interrupt
    loop.run_until_complete(close())
    # Cancel any other lingering tasks and such
finally:
    loop.close()

因此,对您当前尝试的实施而言,没有回报但准确的答案很简单……您不能。

如果您想在响应中或通过消息提供有关您使用的网络服务器库的更多信息,我可以帮助您制作一些功能性的东西。

如果您的网络服务器完全集成了 asyncio,那么您最好的办法是查看该库是否有办法将任务添加到其现有的事件循环中,或者您是否将任务传递给它。 Sanic 在其装饰器启动/关闭方法(例如 after_server_start 等)中允许这样做。将机器人实例的引用存储在某处并根据需要传递它。

我会尝试关注这里的回复或 DM 并尝试帮助您正常工作,我们可以在此处发布更新的代码答案,在更复杂的情况下使用 discord.py 缺乏可靠的答案在其他应用程序/网络服务中,我刚刚遇到了一个类似的问题,编写了一个接受网络钩子数据并基于某些过滤器将嵌入发布到适当渠道的 discord.py 机器人。