[英]Is there a way to run an asyncio coroutine using atexit?
I'm working on a bot using `discord.py.我正在使用 `discord.py 开发一个机器人。 The bot makes/deletes several channels, and connects to a SQLite database.该机器人创建/删除多个频道,并连接到 SQLite 数据库。 If the bot were to crash, I want it to如果机器人崩溃了,我希望它能
Here's the shutdown coroutine:这是关闭协程:
async def shutdown(self):
print("Shutting down Canvas...")
for ch in self.active_channels:
await client.delete_channel(ch)
self.db.close()
Things I've tried:我尝试过的事情:
# Canv is the interface between the bot and the data we're collecting
atexit.register(canv.shutdown)
bot.run(TOKEN)
try:
bot.loop.run_until_complete(bot.start(TOKEN))
except KeyboardInterrupt or InterruptedError:
bot.loop.run_until_complete(canv.shutdown())
finally:
bot.loop.close()
from async_generator import asynccontextmanager
@asynccontextmanager
async def cleanup_context_manager():
try:
yield
finally:
await canv.shutdown()
with cleanup_context_manager():
bot.run(TOKEN)
None of these run canv.shutdown()
, which is an asyncio.coroutine
.这些都不运行canv.shutdown()
,这是一个asyncio.coroutine
。 How do ensure this code gets run on every type of exit?如何确保此代码在每种类型的退出时都运行?
I used this post for some info, and I think it's the closest to what I want.我用这篇文章获取了一些信息,我认为它最接近我想要的。
You can try something like this你可以尝试这样的事情
import asyncio
import atexit
@atexit.register
def shutdown(self):
print("Shutting down Canvas...")
loop = asyncio.get_event_loop()
loop.run_until_complete(await_delete_channels())
self.db.close()
async def await_delete_channels(self):
# # Works but it is better to do it asynchronously
# for ch in self.active_channels:
# await client.delete_channel(ch)
#
# Doing delete_channels() asynchronously
delete_channels = [client.delete_channel(ch) for ch in self.active_channels]
await asyncio.wait(delete_channels, return_when=asyncio.ALL_COMPLETED)
Try:尝试:
try:
bot.loop.run_until_complete(bot.start(TOKEN))
finally:
bot.loop.run_until_complete(canv.shutdown())
bot.loop.close()
You want to delete channels and close db on every kind of script shutdown, not only on crash, right?您想在每种脚本关闭时删除频道并关闭数据库,而不仅仅是在崩溃时,对吗?
Otherwise, try:否则,尝试:
try:
bot.loop.run_until_complete(bot.start(TOKEN))
except Exception:
bot.loop.run_until_complete(canv.shutdown())
raise
finally:
bot.loop.close()
Upd:更新:
According to link you provided:根据您提供的链接:
The information of the exception rasied and the exception itself can be retreived with a standard call to sys.exc_info().可以通过对 sys.exc_info() 的标准调用来检索引发的异常信息和异常本身。
Let's try it out:让我们试试看:
import sys
try:
bot.loop.run_until_complete(bot.start(TOKEN))
finally:
if sys.exc_info() != (None, None, None):
bot.loop.run_until_complete(canv.shutdown())
bot.loop.close()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.