如何使用asyncio.Protocol子类定期发送数据(How to send data peri

2019-11-05 03:50发布

我有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有事时最正确的方法是什么?

Answer 1:

我怎么能对一些外部事件发生时发送一些数据?

最简单的方法是在产卵协程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_connectionopen_connection和从地上爬起来使用流API。 这样,你可以使用协程一路,而不必担心回调/协程阻抗失配。

在一个不相关的音符, try之后except: pass是一个反模式 -考虑捕获特定的异常,而不是,或至少登录异常。



文章来源: How to send data periodically with asyncio.Protocol subclass