与 python3 asyncio 建立连接
Posted
技术标签:
【中文标题】与 python3 asyncio 建立连接【英文标题】:Making connections with python3 asyncio 【发布时间】:2015-05-27 13:45:28 【问题描述】:我正在尝试同时连接到多个服务器。我目前正在使用loop.create_connection
,但它在第一个无响应的服务器处冻结。
gsock = loop.create_connection(lambda: opensock(sid), server, port)
transport, protocol = loop.run_until_complete(gsock)
我尝试对此进行线程化,但它在使用的 sid 值以及各种错误(例如 RuntimeError: Event loop is running
和 RuntimeError: Event loop stopped before Future completed
)方面产生了问题。另外,根据我的变量(虽然混淆了),当transport, protocol = loop.run_until_complete(gsock)
抛出异常时,协议的connection_made()
方法会被执行。
我对 asyncio 模块不太了解,所以请尽可能全面。我认为我不需要读取器/写入器变量,因为读取应该自动完成并触发data_received()
方法。
谢谢。
【问题讨论】:
【参考方案1】:您可以通过同时调度所有协程来同时连接到多个服务器,而不是使用loop.run_until_complete
单独建立每个连接。一种方法是使用asyncio.gather
来安排它们并等待它们完成:
import asyncio
# define opensock somewhere
@asyncio.coroutine
def connect_serv(server, port):
try:
transport, protocol = yield from loop.create_connection(lambda: opensock(sid), server, port)
except Exception:
print("Connection to : failed".format(server, port))
loop = asyncio.get_event_loop()
loop.run_until_complete(
asyncio.gather(
connect_serv('1.2.3.4', 3333),
connect_serv('2.3.4.5', 5555),
connect_serv('google.com', 80),
))
loop.run_forever()
这将同时启动对gather
的调用中列出的所有三个协程,这样如果其中一个挂起,其他的就不会受到影响;他们将能够在其他连接挂起时继续他们的工作。然后,如果它们都完成了,loop.run_forever()
将被执行,这将允许您的程序继续运行,直到您停止循环或终止程序。
您提到的reader
/writer
变量只有在您使用asyncio.open_connection
连接到服务器时才相关,而不是create_connection
。它使用 Stream API,这是一个比create_connection
使用的基于协议/传输的 API 更高级别的 API。真正由您决定您喜欢使用哪个。 asyncio
文档中有 examples 和 both,如果您想查看比较。
【讨论】:
非常感谢,我会试试你的技术。 我仍然想知道在 run_forever() 运行时是否可以使用 run_until_complete()。我想我会在重写后尝试。 实际上这不是一个可行的解决方案,因为套接字不是完全活动的(除非所有服务器连接都及时成功)。程序挂起,等待与服务器的连接之一。 @baudsmoke 我不确定你的意思。哪些套接字未完全激活?具体是什么挂?该程序旨在阻止run_until_complete
调用,如果对connect_serv
的调用之一永远不会返回,则可能永远阻塞。但是,未挂起的 connect_serv
调用应该可以继续正常工作。以上是关于与 python3 asyncio 建立连接的主要内容,如果未能解决你的问题,请参考以下文章
Python 3.5.1 - Asyncio - 检查套接字客户端是不是已断开连接
深究Python中的asyncio库-asyncio简介与关键字
我如何将crossbar客户端(python3,asyncio)与tkinter集成