2016-05-22 25 views
11

Vorrei collegarmi a una presa di rete tramite asyncio e websockets, con un formato come mostrato di seguito. Come potrei essere in grado di realizzare questo?Come posso implementare le websocket asyncio in una classe?

from websockets import connect 


class EchoWebsocket: 

    def __init__(self): 
     self.websocket = self._connect() 

    def _connect(self): 
     return connect("wss://echo.websocket.org") 

    def send(self, message): 
     self.websocket.send(message) 

    def receive(self): 
     return self.websocket.recv() 

echo = EchoWebsocket() 
echo.send("Hello!") 
print(echo.receive()) # "Hello!" 

risposta

12

Come scrivere programmi asincroni?

  1. È necessario definire funcs asincroni con async
  2. Si dovrebbe chiamata asincrona funcs con await
  3. È necessario event loop per avviare il programma di asincrona

Tutti gli altri è quasi stesso con Python regolare programmi.

import asyncio 
from websockets import connect 


class EchoWebsocket: 
    async def __aenter__(self): 
     self._conn = connect("wss://echo.websocket.org") 
     self.websocket = await self._conn.__aenter__()   
     return self 

    async def __aexit__(self, *args, **kwargs): 
     await self._conn.__aexit__(*args, **kwargs) 

    async def send(self, message): 
     await self.websocket.send(message) 

    async def receive(self): 
     return await self.websocket.recv() 


async def main(): 
    async with EchoWebsocket() as echo: 
     await echo.send("Hello!") 
     print(await echo.receive()) # "Hello!" 


if __name__ == '__main__': 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(main()) 

uscita:

Hello! 

Come si vede, il codice è quasi uguale hai scritto.

L'unica differenza è che websockets.connect progettato per essere gestore di contesto asincrono (utilizza __aenter__, __aexit__). È necessario rilasciare la connessione e ti aiuterà anche a eseguire operazioni asincrone durante l'inizializzazione della classe (poiché non abbiamo una versione asincrona di __init__).

Ti consiglio di organizzare la tua classe allo stesso modo. Ma se proprio non si vuole usare il responsabile contesto per qualche motivo è possibile utilizzare nuovo metodo __await__ per rendere l'inizializzazione asincrona e qualche altra funzione asincrona per rilasciare il collegamento:

import sys 
import asyncio 
from websockets import connect 


class EchoWebsocket: 
    def __await__(self): 
     # see: http://stackoverflow.com/a/33420721/1113207 
     return self._async_init().__await__() 

    async def _async_init(self): 
     self._conn = connect("wss://echo.websocket.org") 
     self.websocket = await self._conn.__aenter__() 
     return self 

    async def close(self): 
     await self._conn.__aexit__(*sys.exc_info()) 

    async def send(self, message): 
     await self.websocket.send(message) 

    async def receive(self): 
     return await self.websocket.recv() 


async def main(): 
    echo = await EchoWebsocket() 
    try: 
     await echo.send("Hello!") 
     print(await echo.receive()) # "Hello!" 
    finally: 
     await echo.close() 


if __name__ == '__main__': 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(main()) 

Molti esempi di utilizzo websockets si possono trovare in è docs.

+1

Questa risposta merita un ringraziamento. – pylang

+0

questo si chiude dopo aver ricevuto una risposta. Come potrebbe continuare a ricevere messaggi? – FeedTheWeb

+0

@FeedTheWeb continua a ricevere risposte all'interno di context manager. –

Problemi correlati