【问题标题】:Closing a client关闭客户端
【发布时间】:2021-07-26 11:48:53
【问题描述】:

有如下代码:

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:事件循环在未来完成之前停止”异常。怎么做才对?

【问题讨论】:

    标签: python asynchronous network-programming python-asyncio aiohttp


    【解决方案1】:

    在方法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()
    

    【讨论】:

    • 一切正常。谢谢你。但是我的问题是,您和我的 event_manager 实现之间的技术区别是什么?你能解释一下吗?
    • 每个方法,即aiohttp.ClientSession()session.ws_connect(),都需要async关键字,因此必须是单独的async语句。
    猜你喜欢
    • 2022-08-04
    • 1970-01-01
    • 2011-06-04
    • 2012-08-19
    • 2011-08-29
    • 2011-02-10
    • 2012-03-31
    • 2021-09-14
    • 2010-10-18
    相关资源
    最近更新 更多