簡體   English   中英

有沒有辦法使用 atexit 運行異步協程?

[英]Is there a way to run an asyncio coroutine using atexit?

我正在使用 `discord.py 開發一個機器人。 該機器人創建/刪除多個頻道,並連接到 SQLite 數據庫。 如果機器人崩潰了,我希望它能

  1. 銷毀它創建的所有臨時語音通道。
  2. 斷開與 SQL 數據庫的連接。

這是關閉協程:

async def shutdown(self):
    print("Shutting down Canvas...")
    for ch in self.active_channels:
        await client.delete_channel(ch)
    self.db.close()

我嘗試過的事情:

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

這些都不運行canv.shutdown() ,這是一個asyncio.coroutine 如何確保此代碼在每種類型的退出時都運行?

我用這篇文章獲取了一些信息,我認為它最接近我想要的。

你可以嘗試這樣的事情

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:
    bot.loop.run_until_complete(bot.start(TOKEN))
finally:
    bot.loop.run_until_complete(canv.shutdown())
    bot.loop.close()

您想在每種腳本關閉時刪除頻道並關閉數據庫,而不僅僅是在崩潰時,對嗎?

否則,嘗試:

try:
    bot.loop.run_until_complete(bot.start(TOKEN))
except Exception:
    bot.loop.run_until_complete(canv.shutdown())
    raise
finally:
    bot.loop.close()

更新:

根據您提供的鏈接:

可以通過對 sys.exc_info() 的標准調用來檢索引發的異常信息和異常本身。

讓我們試試看:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM