Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 接收到从asyncio.Protocol.data\u调用协同路由_Python_Python Asyncio - Fatal编程技术网

Python 接收到从asyncio.Protocol.data\u调用协同路由

Python 接收到从asyncio.Protocol.data\u调用协同路由,python,python-asyncio,Python,Python Asyncio,这类似于,但我认为有必要提出一个新问题 我有这样一个简单的服务器 loop.create_unix_server(lambda: protocol, path=serverSocket) 如果我这样做,效果很好 def data_received(self, data): data = b'data reply' self.send(data) 我的客户得到了答复。但是我不能让它与任何类型的asyncio调用一起工作。我尝试了以下所有方法,但没有一个奏效 @asyncio.

这类似于,但我认为有必要提出一个新问题

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

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
修饰
接收到的数据,我得到的不是从中产生的)好的,我得到的是在
接收到的数据中使用收益是不对的

如果我尝试一个新的事件循环,如下所示,它挂起在
run\u中,直到\u完成

    loop = asyncio.new_event_loop()
    task = loop.create_task(self.go())
    loop.run_until_complete(task)
    data = task.result()
    self.send(data)
@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)
如果我使用一个
Future
,它也会挂起在
run\u中,直到完成

    loop = asyncio.new_event_loop()
    task = loop.create_task(self.go())
    loop.run_until_complete(task)
    data = task.result()
    self.send(data)
@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\u 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)

我真的有点卡住了,希望能给我一些关于该看什么的建议。

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

@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\u received
中调用协同程序是不允许的,因为调用者不会试图从
中屈服,在
data\u received
中创建/运行一个新的事件循环总是会阻塞主事件循环,直到内部事件循环完成其工作


您只需要计划主事件循环的一些工作(
asyncio.async
/
loop.create_task()
),并计划在工作完成时运行回调(
add_done_callback
)。

您好,感谢您的回复-这在我的代码中确实有效。我只是将它集成到我的非平凡代码(具有调用堆栈等)中,我曾想过使用回调,但我认为屈服/tasks/futures是最新的方法,它的好处是不用担心调用堆栈或如何将数据放入回调。你知道为什么内环不能完成它的工作吗?或者为什么未来的方法不能与主循环一起工作?哦,我猜内部循环正在等待被阻塞的外部循环来执行一些IO等操作。@Dave
asyncio
显然更倾向于使用协同程序风格的方法来实现更高级别的使用,但是像协议这样的低级功能仍然使用回调风格。如果您想使用协同路由,那么可以使用流对象而不是协议?