Python-如何使用asyncio并发运行多个协同路由?

Python-如何使用asyncio并发运行多个协同路由?,python,python-3.x,websocket,python-asyncio,Python,Python 3.x,Websocket,Python Asyncio,我正在使用该库在Python3.4中创建websocket服务器。下面是一个简单的echo服务器: 导入异步IO 导入WebSocket @异步协同程序 def连接_处理程序(websocket,路径): 尽管如此: msg=来自websocket.recv()的收益率 如果msg为None:#连接丢失 打破 websocket.send的收益(msg) start\u server=websockets.service(连接处理程序'localhost',8000) asyncio.get_e

我正在使用该库在Python3.4中创建websocket服务器。下面是一个简单的echo服务器:

导入异步IO
导入WebSocket
@异步协同程序
def连接_处理程序(websocket,路径):
尽管如此:
msg=来自websocket.recv()的收益率
如果msg为None:#连接丢失
打破
websocket.send的收益(msg)
start\u server=websockets.service(连接处理程序'localhost',8000)
asyncio.get_event_loop()。运行_直到完成(启动服务器)
asyncio.get_event_loop().永远运行_()
假设我们——另外——希望在发生事件时向客户机发送消息。为了简单起见,让我们每隔60秒定期发送一条消息。我们怎么做?我的意思是,因为
connection\u handler
一直在等待传入的消息,所以服务器只有在收到来自客户端的消息后才能采取行动,对吗?我错过了什么


也许这个场景需要一个基于事件/回调的框架,而不是一个基于协同路由的框架

TL;DR用于同时运行多个协同路由


也许这个场景需要一个基于事件/回调的框架,而不是一个基于协同路由的框架?龙卷风

不,你不需要任何其他的框架。异步应用程序与同步应用程序的整体思想是,它在等待结果时不会阻塞。不管它是如何实现的,使用协同路由或回调

我的意思是,因为连接处理程序一直在等待传入的消息,所以服务器只有在收到来自客户端的消息后才能采取行动,对吗?我错过了什么

在同步应用程序中,您将编写类似于
msg=websocket.recv()
,这将阻止整个应用程序,直到您收到消息为止(如您所述)。但在异步应用程序中则完全不同

当您执行
msg=yield from websocket.recv()
时,您会说这样的话:暂停执行
connection\u handler()
,直到
websocket.recv()
将产生一些结果。在协同程序内部使用
yield from
将控制权返回到事件循环,以便在等待
websocket.recv()的结果时可以执行其他一些代码。请参阅以更好地了解协同程序的工作原理

假设我们——另外——希望在发生事件时向客户机发送消息。为了简单起见,让我们每隔60秒定期发送一条消息。我们怎么做

在对执行阻塞调用之前,可以使用运行任意多个协程

导入异步IO
导入WebSocket
#在这里,我们将存储用于发送定期消息的所有活动连接
连接=[]
@异步协同程序
def连接\u处理程序(连接,路径):
连接。附加(连接)#将连接添加到池
尽管如此:
msg=从connection.recv()获得的收益
如果msg为None:#连接丢失
连接。删除(连接)#当客户端断开连接时,从池中删除连接
打破
其他:
打印(“<{}.”格式(msg))
从connection.send(msg)获得的收益
打印('>{}'.格式(msg))
@异步协同程序
def定期发送_():
尽管如此:
从asyncio.sleep(5)#切换到其他代码并在5秒内继续执行
对于连接中的连接:
打印(“>发生定期事件”。)
从connection.send(周期性事件发生)获得收益#向每个连接的客户端发送消息
start\u server=websockets.service(连接处理程序'localhost',8000)
asyncio.get_event_loop()。运行_直到完成(启动服务器)
asyncio.async(send_periodically())#在阻塞调用之前,我们计划我们的协同路由以发送定期消息
asyncio.get_event_loop().永远运行_()
下面是一个示例客户机实现。它要求您输入name,从echo服务器接收它,等待来自服务器的另外两条消息(这是我们的定期消息),然后关闭连接

import asyncio

import websockets


@asyncio.coroutine
def hello():
    connection = yield from websockets.connect('ws://localhost:8000/')
    name = input("What's your name? ")
    yield from connection.send(name)
    print("> {}".format(name))
    for _ in range(3):
        msg = yield from connection.recv()
        print("< {}".format(msg))

    yield from connection.close()


asyncio.get_event_loop().run_until_complete(hello())
导入异步IO
导入WebSocket
@异步协同程序
def hello():
connection=从websockets.connect中产生('ws://localhost:8000/'))
name=输入(“你叫什么名字?”)
从连接中获得收益。发送(名称)
打印(“>{}”。格式(名称))
对于范围(3)内的uu:
msg=从connection.recv()获得的收益
打印(“<{}”。格式(msg))
从connection.close()获得的收益
asyncio.get_event_loop()。运行_直到完成(hello())
要点:

  • 在Python 3.4.4中,
    asyncio.async()
    被重命名为
  • 有一些特殊的调度方法,但它们不适用于协同程序

  • 同样的问题,直到我在这里看到完美的样本,我才找到解决方案:


    因此,我可以处理多个协同路由任务,如心跳和redis订阅。

    我很惊讶
    没有提到聚集

    从:


    回答得很好,谢谢!我理解什么是协同程序,但我仍在尝试了解异步IO框架。你的回答帮了大忙。你解决问题了吗?我也有类似的问题,我试过你教的链接。但是我不能解决我的问题。请给我一些建议我的问题,谢谢这个。。。虽然我的问题不一样,但这个解决方案帮助了很多。这是本线程中所有建议的解决方案中最简单的一个,可以在Python3.8上确认,简单易行,它就是有效的。
    import asyncio
    
    import websockets
    
    
    @asyncio.coroutine
    def hello():
        connection = yield from websockets.connect('ws://localhost:8000/')
        name = input("What's your name? ")
        yield from connection.send(name)
        print("> {}".format(name))
        for _ in range(3):
            msg = yield from connection.recv()
            print("< {}".format(msg))
    
        yield from connection.close()
    
    
    asyncio.get_event_loop().run_until_complete(hello())
    
     done, pending = await asyncio.wait(
            [listener_task, producer_task],
            return_when=asyncio.FIRST_COMPLETED)  # Important
    
    import asyncio
    
    async def factorial(name, number):
        f = 1
        for i in range(2, number + 1):
            print(f"Task {name}: Compute factorial({i})...")
            await asyncio.sleep(1)
            f *= i
        print(f"Task {name}: factorial({number}) = {f}")
    
    async def main():
        # Schedule three calls *concurrently*:
        await asyncio.gather(
            factorial("A", 2),
            factorial("B", 3),
            factorial("C", 4),
        )
    
    asyncio.run(main())
    
    # Expected output:
    #
    #     Task A: Compute factorial(2)...
    #     Task B: Compute factorial(2)...
    #     Task C: Compute factorial(2)...
    #     Task A: factorial(2) = 2
    #     Task B: Compute factorial(3)...
    #     Task C: Compute factorial(3)...
    #     Task B: factorial(3) = 6
    #     Task C: Compute factorial(4)...
    #     Task C: factorial(4) = 24