从asyncio.Protocol.data调用协程

这与asyncio.Protocol.data_received中的调用协程类似,但我认为它需要一个新的问题。

我有这样一个简单的服务器设置

loop.create_unix_server(lambda: protocol, path=serverSocket)

它工作正常,如果我这样做

 def data_received(self, data):
    data = b'data reply'
    self.send(data)

我的客户得到答复。 但我无法使用任何类型的asyncio调用。 我尝试了以下所有内容,但都没有工作。

@asyncio.coroutine
def go(self):
    yield from asyncio.sleep(1, result = b'data reply')

def data_received(self, data):
    print('Data Received', flush=True)

    task = asyncio.get_event_loop().create_task(self.go())
    data = yield from asyncio.wait_for(task,10)
    self.send(data)

那个挂起来并且什么都不印(如果我用@asyncio.coroutine装饰data_received ,我得到的并不是这样)OK,我知道在data_received中使用yield是不对的。

如果我尝试一个新的事件循环,如下所示,该循环在run_until_complete中挂起

    loop = asyncio.new_event_loop()
    task = loop.create_task(self.go())
    loop.run_until_complete(task)
    data = task.result()
    self.send(data)

如果我使用Future ,那也会挂在run_until_complete

@asyncio.coroutine
def go(self, future):
    yield from asyncio.sleep(1)
    future.set_result(b'data reply')

def data_received(self, data):
    print('Data Received', flush=True)

    loop = asyncio.new_event_loop()
    future = asyncio.Future(loop=loop)
    asyncio.async(self.go(future))
    loop.run_until_complete(future)
    data = future.result()
    self.send(data)

下面的代码会很接近,但是它会立即返回,结果是asyncio.coroutines.CoroWrapper ,意味着wait_for行会立即返回未完成的任务?

@asyncio.coroutine
def go(self):
    return(yield from asyncio.sleep(3, result = b'data reply'))

@asyncio.coroutine
def go2(self):
    task = asyncio.get_event_loop().create_task(self.go())
    res = yield from asyncio.wait_for(task, 10)
    return result

def data_received(self, data):
    print('Data Received', flush=True)

    data = self.go2()
    self.send(data)

我真的有点被卡住了,并且希望看到一些关于看什么的指示。


您需要将您的协同程序添加到事件循环中,然后在协程完成时使用Future.add_done_callback来处理结果:

@asyncio.coroutine
def go(self):
    return(yield from asyncio.sleep(3, result = b'data reply'))

def data_received(self, data):
    print('Data Received', flush=True)

    task = asyncio.async(self.go()) # or asyncio.get_event_loop().create_task()
    task.add_done_callback(self.handle_go_result)

def handle_go_result(self, task):
    data = task.result()
    self.send(data)

直接在data_received直接调用协程是不允许的,因为调用者不会尝试yield from它中yield from ,并且在data_received创建/运行新的事件循环将最终阻止主事件循环,直到内部事件循环完成其工作。

您只想安排一些与主事件循环( asyncio.async / loop.create_task() )一起工作,并安排回调以在工作完成时运行( add_done_callback )。

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

上一篇: Calling a coroutine from asyncio.Protocol.data

下一篇: Understanding Python Concurrency with Asyncio