Как использовать асинхронные сопрограммы как генератор? - PullRequest
1 голос
/ 13 июня 2019

Я хочу разработать средство наблюдения за веб-сокетами на python таким образом, чтобы при отправке sth он должен был ждать получения ответа (что-то вроде блокировки программирования сокетов). Я знаю, что это странно, в основном я хочу сделать инструмент командной строки Python 3.6, который может обмениваться данными с сервером, сохраняя то же самое подключение к сети для всех команд, поступающих от пользователя.

Я вижу, что приведенный ниже фрагмент довольно типичен для Python 3.6.

import asyncio
import websockets
import json
import traceback

async def call_api(msg):
   async with websockets.connect('wss://echo.websocket.org') as websocket:
       await websocket.send(msg)
       while websocket.open:
           response = await websocket.recv()
           return (response)

print(asyncio.get_event_loop().run_until_complete(call_api("test 1")))

print(asyncio.get_event_loop().run_until_complete(call_api("test 2")))

но это создаст новое соединение ws для каждой команды, которая побеждает цель. Можно сказать, что вы должны использовать асинхронный обработчик, но я не знаю, как синхронизировать ответ ws с пользовательским вводом из командной строки.

Я думаю, что если бы я мог заставить асинхронную сопрограмму (call_api) работать как генератор, где вместо оператора return вместо оператора return есть оператор yield, то я, вероятно, мог бы сделать что-то вроде beow:


async def call_api(msg):
   async with websockets.connect('wss://echo.websocket.org') as websocket:
       await websocket.send(msg)
       while websocket.open:
           response = await websocket.recv()
           msg = yield (response)

generator = call_api("cmd1")

cmd  = input(">>>")

while cmd != 'exit'
    result = next(generator.send(cmd))
    print(result)
    cmd  = input(">>>")


Пожалуйста, дайте мне знать ваши ценные комментарии.

Спасибо

1 Ответ

1 голос
/ 13 июня 2019

Этого можно достичь с помощью асинхронного генератора (PEP 525) .

Вот рабочий пример:

import random
import asyncio


async def accumulate(x=0):
    while True:
        x += yield x
        await asyncio.sleep(1)


async def main():
    # Initialize
    agen = accumulate()
    await agen.asend(None)
    # Accumulate random values
    while True:
        value = random.randrange(5)
        print(await agen.asend(value))


asyncio.run(main())
...