I'm working on a bot using `discord.py. The bot makes/deletes several channels, and connects to a SQLite database. 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
. 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().
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With