2016-05-22 3 views
11

Ich möchte eine Verbindung zu einem Websocket über asyncio und websockets, mit einem Format wie unten gezeigt. Wie könnte ich das erreichen?Wie kann ich asyncio-Websockets in einer Klasse implementieren?

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!" 

Antwort

12

Wie schreibe ich asynchrone Programme?

  1. Sie sollten async funcs mit async
  2. definieren Sie sollten await mit Asynchron funcs rufen
  3. Sie müssen event loop auf Ihr Asynchron-Programm

Alle anderen fast die gleiche ist wie bei normalen Python zu starten Programme.

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()) 

Ausgang:

Hello! 

Wie Sie sehen, Code ist fast gleich wie Sie geschrieben haben.

Der einzige Unterschied ist, dass websockets.connect als asynchronen Kontextmanager (es verwendet __aenter__, __aexit__) entwickelt wurde. Es ist notwendig, die Verbindung aufzuheben und Sie können auch asynchrone Operationen während der Klasseninitialisierung ausführen (da wir keine asynchrone Version von __init__ haben).

Ich rate Ihnen, Ihre Klasse auf die gleiche Weise zu organisieren. Aber wenn Sie wirklich Kontext-Manager aus irgendeinem Grund nicht verwenden möchten, können Sie neue __await__ Methode verwenden, um asynchrone Initialisierung und einige andere Asynchron-Funktion freigeben Verbindung herzustellen:

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()) 

Viele Beispiele für die Verwendung websockets finden Sie in es ist docs.

+1

Diese Antwort verdient einen Dank. – pylang

+0

Dies schließt, nachdem es eine Antwort erhalten hat. Wie könnte es weiterhin Nachrichten empfangen? – FeedTheWeb

+0

@FeedTheWeb erhalten nur Antworten innerhalb des Kontextmanagers. –

Verwandte Themen