Python-如何使用asyncio并发运行多个协同路由?
我正在使用该库在Python3.4中创建websocket服务器。下面是一个简单的echo服务器: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
导入异步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