具有异步计时器的Python异步websocket客户端

时间:2016-02-20 22:16:14

标签: python websocket python-asyncio

我需要有一个长期运行的websocket客户端,它接收来自websocket服务器的推送消息,我需要监控客户端的连接状态:如果连接断开,我需要找出答案。

我的方法是定期记录一个常量字符串,并在未检测到日志消息的情况下触发警报。

我的想法:1)有一个websocket客户端响应不规则传入的消息。 2)同时有一个循环,当websocket客户端抛出一个ConnectionClosed执行时停止记录消息。

我对新的3.5异步语法很感兴趣。 This websocket实现特别基于asyncio。文档中的client看起来与我需要的完全一样。

但是,我不知道如何添加第二个协同程序,当websocket连接抛出ConnectionClosed时,我的日志记录语句会以某种方式停止。

以下是启动对话的内容,但由于alive方法阻止了事件循环,因此无法正常工作。我正在寻找的是同时运行这两种方法的优雅解决方案。

#!/usr/bin/env python

import asyncio
import logging

import websockets

logger = logging.getLogger(__name__)

is_alive = True


async def alive():
    while is_alive:
        logger.info('alive')
        await asyncio.sleep(300)


async def async_processing():
    async with websockets.connect('ws://localhost:8765') as websocket:
        while True:
            try:
                message = await websocket.recv()
                print(message)

            except websockets.exceptions.ConnectionClosed:
                print('ConnectionClosed')
                is_alive = False
                break


asyncio.get_event_loop().run_until_complete(alive())
asyncio.get_event_loop().run_until_complete(async_processing())

1 个答案:

答案 0 :(得分:5)

实际上run_until_complete在此处阻止,因为它会等到alive完成。

您可以通过两个步骤解决它:

  1. 使用asyncio.ensure_future计划协同程序(立即运行而不等待结果),每个返回任务。
  2. 等待任务完成asyncio.wait
  3. 代码如:

    tasks = [
       asyncio.ensure_future(alive()),
       asyncio.ensure_future(async_processing())
    ]
    asyncio.get_event_loop().run_until_complete(asyncio.wait(tasks))
    

    正如@Vincent提到wait接受任务,所以ensure_future是不必要的:

    asyncio.get_event_loop().run_until_complete(asyncio.wait([   
       alive(),
       async_processing()
    ]))