2016-02-20 3 views
1

Je dois avoir un client websocket à long terme qui reçoit des messages push depuis un serveur websocket et j'ai besoin de surveiller l'état de connexion du client: si la connexion tombe en panne, je dois le savoir.Client async websocket Python avec timer asynchrone

Mon approche consiste à consigner périodiquement une chaîne constante et à déclencher une alarme si jamais le message de journal n'est pas détecté.

Mon idée: 1) avoir un client websocket qui répond aux messages entrants irrégulièrement. Et 2) en même temps avoir une boucle qui arrête la journalisation d'un message lorsque le client websocket lève une exception ConnectionClosed.

Je suis intrigué par la nouvelle syntaxe asynchrone 3.5. This websocket La mise en œuvre est spécifiquement basée sur l'asyncio. Le client dans les documents ressemble exactement à ce dont j'ai besoin.

Cependant, je ne sais pas comment ajouter une deuxième coroutine qui fait mes instructions de journalisation et s'arrête en quelque sorte lorsque la connexion websocket jette le ConnectionClosed.

Voici quelque chose pour démarrer la conversation, mais cela ne fonctionne pas car la méthode active bloque la boucle d'événements. Ce que je cherche est une solution élégante pour exécuter les deux méthodes simultanément.

#!/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()) 

Répondre

4

En fait, le run_until_complete bloque ici, car il attend que alive arrivée.

Vous pouvez résoudre avec 2 étapes:

  1. horaire coroutines avec asyncio.ensure_future (fonctionne immédiatement sans attendre les résultats), chaque tâche de retour.
  2. attente pour les tâches pour obtenir terminé avec asyncio.wait

Le code comme:

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

Comme mentionné @Vincent wait accepte les tâches, donc ensure_future est inutile:

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

fonctionne comme un charme. Merci beaucoup. –

+1

Vous pouvez passer une liste de coroutines à 'asyncio.wait', pas besoin d'utiliser' asyncio.ensure_future' dans votre exemple. – Vincent