调用协程并在asyncio.Protocol.data中获得未来

我需要在asyncio循环内获得未来的结果,它类似于从asyncio.Protocol.data_received调用协程

但是asyncio和PY34中的asyncio是完全不同的,下面是可以在PY34中正确运行的代码,但是在PY35中,它将在yield from停顿并从不返回。

# PY34
class RelayClient(asyncio.Protocol):
    pass

class Server(asyncio.Protocol):
    def data_received(self, data):
        # I need to connect to another address, and get future result at current function.
        # Also I could not run loop.run_until_complete().
        loop = asyncio.get_event_loop()
        result = yield from loop.create_connection(RelayClient, 'www.google.com', 443)
        do_some_thing_with_result(result)

那么,如何在python 3.5中做到这一点?

任何建议表示赞赏。


您不能等待来自不是协程的函数的协程。 data_received不是协程,所以在注释中提到,您需要使用ensure_future helper从协同程序创建“背景”任务。

不需要开始使用回调:

async def do_stuff(data):
        result = await loop.create_connection(RelayClient, 'www.google.com', 443)
       await do_some_thing_with_result(result)

class Server(asyncio.Protocol):
    def data_received(self, data):
        asyncio.ensure_future(do_stuff(data))

然而,我会指出,asyncio不会给您带来任何数据,因为data_received将被您期望的完整数据调用。 通常你在Protocol看到的模式看起来很像这样:

async def process_line(line):
    ...

class Server(asyncio.Protocol):
    def __init__(self):
        self.buffer = b''

    def data_received(self, data):
        self.buffer += data

        if b'n' not in self.buffer:
            return

        line, self.buffer = self.buffer.split(b'n')
        fut = asyncio.ensure_future(process_line(line))
        fut.add_done_callback(self._handle_exception)

    def _handle_exception(self, fut):
        if fut.exception() is not None:
            print('Processing failed', fut.exception())

(这只是一个例子,它复制缓冲区的方式太多了,而且在大多数生产用例中效率很低)

链接地址: http://www.djcxy.com/p/53231.html

上一篇: Calling coroutine and getting future in asyncio.Protocol.data

下一篇: Conditional in a coroutine based on whether it was called again?