[英]Cannot close a running event loop
What is the way to close the discord.py bot loop once tasks are done?任务完成后关闭 discord.py 机器人循环的方法是什么?
Added:添加:
nest_asyncio.apply()
Tried:试过:
bot.logout(), bot.close(), bot.cancel()
Code:代码:
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)
I can be able to send messages to discord users using id and discord bot.我可以使用 id 和 discord 机器人向 discord 用户发送消息。 But, even after, django view api is continuously running and getting the error.
但是,即使之后,django 视图 api 仍在继续运行并出现错误。 It needs to return a response message - discord messages sent.
它需要返回一个响应消息 - discord 消息发送。
Error:错误:
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
These are the versions:这些是版本:
Python 3.6.4, Django 3.1, discord.py 1.7.3, Asyncio, Anaconda-4.9.2, Windows-10
I've not used older versions so I can't attest to the accuracy of this answer for pre-2021 releases (v1.6.0+) Discord.py.我没有使用旧版本,因此我无法证明此答案对于 2021 之前版本 (v1.6.0+) Discord.py 的准确性。
When starting a discord Client or Bot via run(*args, **kwargs)
there is actually no class method to stop it.通过
run(*args, **kwargs)
启动 discord 客户端或机器人时,实际上没有 class 方法可以停止它。
Per the Discord.py Documentations Discord.py discord.Client.run :根据 Discord.py 文档Discord.py discord.Client.run :
A blocking call that abstracts away the event loop initialisation from you.
从您那里抽象出事件循环初始化的阻塞调用。
If you want more control over the event loop then this function should not be used.
如果您想对事件循环进行更多控制,则不应使用此 function。 Use start() coroutine or connect() + login()
使用 start() 协程或 connect() + login()
And it's effectively equal to:它实际上等于:
# 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()
So the unrewarding but accurate answer with your current attempted implementation is simply... you can't.因此,您当前尝试实施的无回报但准确的答案很简单……您不能。
If you wanna drop some more info on the webserver library your using in response or via a message, I can help craft you something functional.如果您想在响应或通过消息使用的网络服务器库上提供更多信息,我可以帮助您制作一些实用的东西。
If your webserver is fully asyncio integrated, your best bet is seeing if the library has a way to add tasks to its existing event loop, or if you pass one to it.如果您的网络服务器完全集成了 asyncio,那么最好的办法是查看库是否有办法将任务添加到其现有的事件循环中,或者您是否将任务传递给它。 Sanic allows for this in its decorator startup/shutdown methods (ex. after_server_start, etc).
Sanic 在其装饰器启动/关闭方法(例如 after_server_start 等)中允许这样做。 Store the reference to the bot instance somewhere and pass it around as needed.
将对机器人实例的引用存储在某处并根据需要传递它。
I'll try and keep an eye on here for a response or DM and try to help get you functional and we can post updated code answer here, there's a big lack of solid answers for using discord.py in more complex cases within other applications/webservices and I just ran into a similiar issue with writing a discord.py bot that accepted webhook data and posted embeds to appropriate channels based on some filters.我将尝试关注这里的回复或 DM 并尝试帮助您发挥作用,我们可以在此处发布更新的代码答案,在其他应用程序/Web 服务中更复杂的情况下使用 discord.py 缺乏可靠的答案我刚刚遇到了一个类似的问题,即编写一个 discord.py 机器人,它接受 webhook 数据并根据一些过滤器将嵌入发布到适当的频道。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.