从 asyncio.Protocol.data_received 调用协程
Calling a coroutine from asyncio.Protocol.data_received
这与 Calling coroutines in 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
调用一起使用。我尝试了以下所有方法,none 成功了。
@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
我知道那不是 yield from)好的,我知道在 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)
以下内容接近,但它立即 returns 并且结果的类型为 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
它,并且 creating/running 内部有一个新的事件循环data_received
将始终阻塞主事件循环,直到内部事件循环完成其工作。
您只想在主事件循环中安排一些工作 (asyncio.async
/loop.create_task()
),并在工作完成后安排对 运行 的回调 (add_done_callback
).
这与 Calling coroutines in 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
调用一起使用。我尝试了以下所有方法,none 成功了。
@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
我知道那不是 yield from)好的,我知道在 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)
以下内容接近,但它立即 returns 并且结果的类型为 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
它,并且 creating/running 内部有一个新的事件循环data_received
将始终阻塞主事件循环,直到内部事件循环完成其工作。
您只想在主事件循环中安排一些工作 (asyncio.async
/loop.create_task()
),并在工作完成后安排对 运行 的回调 (add_done_callback
).