关闭客户端

Closing a client

有如下代码:

import asyncio
import aiohttp

aut_token = ("token")

tasks = []
iter_flag = False

class WAPI:

    async def receiver(WAPI_S):
        async for msg in WAPI_S:
            data = msg.json()
            raise aiohttp.ClientError #test

    async def heartbeating(WAPI_S):
        while iter_flag:
            await WAPI_S.send_json({
                            "op": 1,
                            "d": None
                        })
            
            await asyncio.sleep(42.5)

    async def event_manager():
        loop = asyncio.get_running_loop()
        try:
            async with aiohttp.ClientSession().ws_connect("url") as WAPI_S: 
                task_receive = loop.create_task(WAPI.receiver(WAPI_S)); task_heartbeating = loop.create_task(WAPI.heartbeating(WAPI_S))
                tasks.append(task_receive); tasks.append(task_heartbeating)
                await asyncio.gather(*tasks)
        except aiohttp.ClientError:
            global iter_flag
            iter_flag = False
            await asyncio.sleep(44)
            [task.cancel() for task in tasks]
            try:
                loop.close()
            except:
                loop.stop()
                
            
asyncio.run(WAPI.event_manager())

我想在出现异常时正确关闭客户端。我的实现在执行时抛出“RuntimeError:Event loop stopped before Future completed”异常。怎么做才对?

在方法event_manager中,语句:

            async with aiohttp.ClientSession().ws_connect("url") as WAPI_S:

需要替换为:

            async with aiohttp.ClientSession() as session:
                async with session.ws_connect("url") as WAPI_S:

此外,使用列表推导来解决其副作用被认为是反 Pythonic 的。见Is it Pythonic to use list comprehensions for just side effects?所以你真的应该替换:

            [task.cancel() for task in tasks]

与:

            for task in tasks:
                task.cancel()

综合起来:

    async def event_manager():
        loop = asyncio.get_running_loop()
        try:
            async with aiohttp.ClientSession() as session:
                async with session.ws_connect("url") as WAPI_S: 
                    task_receive = loop.create_task(WAPI.receiver(WAPI_S)); task_heartbeating = loop.create_task(WAPI.heartbeating(WAPI_S))
                    tasks.append(task_receive); tasks.append(task_heartbeating)
                    await asyncio.gather(*tasks)
        except aiohttp.ClientError:
            global iter_flag
            iter_flag = False
            await asyncio.sleep(44)
            for task in tasks:
                task.cancel()
            try:
                loop.close()
            except:
                loop.stop()