Jak pisać programy asynchroniczne?
- Należy określić funcs async z
async
- Należy zadzwonić asynchroniczny funcs z
await
- Trzeba event loop aby uruchomić program asynchroniczny
Wszystko inne jest prawie taka sama jak w przypadku zwykłej Pythonie programy.
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())
wyjściowa:
Hello!
Jak widać, kod jest prawie taka sama jak napisałeś.
Jedyna różnica polega na tym, że websockets.connect
został zaprojektowany jako menedżer kontekstów asynchronicznych (używa __aenter__
, __aexit__
). Konieczne jest zwolnienie połączenia, a także ułatwi wykonywanie operacji asynchronicznych podczas inicjowania klasy (ponieważ nie mamy asynchronicznej wersji __init__
).
Radzę zorganizować swoją klasę w ten sam sposób. Ale jeśli naprawdę nie chcesz używać menedżera kontekstowe jakiegoś powodu można korzystać z nowej metody __await__
dokonać inicjalizacji transmisji asynchronicznej i kilka innych funkcji asynchronicznej, aby zwolnić połączenie:
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())
Wiele przykładów wykorzystania websockets
można znaleźć w to jest docs.
Ta odpowiedź zasługuje na podziękowanie. – pylang
to kończy się po otrzymaniu odpowiedzi. Jak mógł kontynuować otrzymywanie wiadomości? – FeedTheWeb
@FeedTheWeb po prostu otrzymywać odpowiedzi wewnątrz menedżera kontekstu. –