键盘中断时关闭ClientSession

Closing ClientSession when keyboard interrupt

我正在用 python 制作一个不和谐的机器人。当用户键入命令时,此机器人会从 url 获取数据并显示出来。我使用 aiohttp 进行异步 http 请求,但是 discord.py 的文档说,

Since it is better to not create a session for every request, you should store it in a variable and then call session.close on it when it needs to be disposed.

所以我更改了所有代码

async with aiohttp.ClientSession() as session:
    async with session.get('url') as response:
        # something to do

进入

# Global variable
session = aiohttp.ClientSession()

async with session.get('url') as response:
    # something to do

所有 http 请求都使用全局定义的 session。但是当我运行这段代码并通过键盘中断(Ctrl + C)停止时,出现了这个警告信息。

Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x0000015A45ADBDD8>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x0000015A464925E8>, 415130.265)]']
connector: <aiohttp.connector.TCPConnector object at 0x0000015A454B3320>

程序因键盘中断而停止时如何关闭ClientSession

我尝试了什么:

我试过跟随,但效果不佳。

  1. 制作 class 并在其 __del__ 中关闭。 __del__ 键盘中断时没有调用。
class Session:
    def __init__(self):
        self._session = aiohttp.ClientSession()

    def __del__(self):
        self._session.close()
  1. main 中的无限循环,并捕获 KeyboardInterrupt。程序被 bot.run() 阻止,因此无法访问代码。
from discord.ext import commands

if __name__ == "__main__":
    bot = commands.Bot()
    bot.run(token) # blocked
    try:
        while(True):
            sleep(1)
    except KeyboardInterrupt:
        session.close()
  1. 当机器人断开连接时关闭会话。 on_disconnect键盘中断时未调用
@bot.event
async def on_disconnect():
    await session.close()

您必须 await 关闭一个 ClientSession 对象:

await session.close()

请注意文档 here 中的 coroutine。您的尝试 #3 可能最适合这个问题,因为它自然是一个 async 函数。

我尝试了以下代码,它似乎运行良好。

import asyncio
import aiohttp

class Session:
    def __init__(self):
        self._session = aiohttp.ClientSession()

    def __del__(self):
        loop = asyncio.get_event_loop()
        loop.run_until_complete(self.close()

    async def close(self):
        await self._session.close()

session = Session()