Как отправлять данные периодически с подклассом asyncio.Protocol - PullRequest
0 голосов
/ 02 сентября 2018

У меня есть подкласс asyncio.Protocol

class MyProtocol(Protocol):
    def __init__(self, exit_future):
        self.exit_future = exit_future

    def connection_made(self, transport):
        self.transport = transport

    def data_received(self, data):
        pass

    def eof_received(self):
        self.exit_future.set_result(True)

    def connection_lost(self, exc):
        self.exit_future.set_result(True)

и сетевое соединение, созданное с помощью

while True:
    try:
        exit_future = Future(loop=loop)
        transport, protocol = await loop.create_connection(lambda: MyProtocol(exit_future), host, port)

        await exit_future
        transport.close()
    except:
        pass

Теперь вопрос: как я могу отправить некоторые данные о каком-то внешнем событии? Например, когда asyncio.Queue не пусто (queue.get не будет блокироваться), что заполняет эту очередь, не связанную с asyncio? Какой самый правильный способ вызова transport.write, когда что-то происходит?

1 Ответ

0 голосов
/ 02 сентября 2018

как я могу отправить некоторые данные о происходящем внешнем событии?

Самый простой способ - создать сопрограмму в connection_made и оставить ее для обработки события в «фоне»:

def connection_made(self, transport):
    self.transport = transport
    loop = asyncio.get_event_loop()
    self._interesting_events = asyncio.Queue()
    self.monitor = loop.create_task(self._monitor_impl())

def connection_lost(self, exc):
    self.exit_future.set_result(True)
    self.monitor.cancel()

async def _monitor_impl(self):
    while True:
        # this can also await asyncio.sleep() or whatever is needed
        event = await self._interesting_events.get()
        self.transport.write(...)

Обратите внимание, что в долгосрочной перспективе, возможно, стоит заменить create_connection на open_connection и использовать API потоков с нуля. Таким образом, вы можете использовать сопрограммы полностью, не беспокоясь о несоответствии обратного вызова / сопрограммы.

На неродственной ноте try, за которой следует except: pass, является анти-паттерном - рассмотрите возможность перехвата определенного исключения или, по крайней мере, регистрации его исключения.

...