Python 如何运行一个不结束而不等待结果的协同程序?
我有一段代码,我想连接到websocket,并通过发送心跳来保持连接的活力。在执行此操作时,我还希望能够将有效负载发送到websocket,但是我一直在等待我的Python 如何运行一个不结束而不等待结果的协同程序?,python,python-3.x,python-asyncio,python-3.6,Python,Python 3.x,Python Asyncio,Python 3.6,我有一段代码,我想连接到websocket,并通过发送心跳来保持连接的活力。在执行此操作时,我还希望能够将有效负载发送到websocket,但是我一直在等待我的keepAlivecorroutine的结果 import asyncio import websockets ws=#path goes here async def sendHeartbeat(socket): message={ "op": 1, "d": 0 } aw
keepAlive
corroutine的结果
import asyncio
import websockets
ws=#path goes here
async def sendHeartbeat(socket):
message={
"op": 1,
"d": 0
}
await socket.send(json.dumps(message))
print("heartbeat sent")
async def keepAlive(socket):
while 1==1:
await sendHeartbeat(socket)
resp=await(socket.recv())
print(resp)
if json.loads(resp)["op"]==11:
#the server sent an ack back
print("ack received")
else:
socket.close()
await asyncio.sleep(10)
async def beginSocket(loop):
async with websockets.connect(ws) as socket:
print(await socket.recv())
await keepAlive(socket)
#payloads would be sent here
print("Hey payloads being sent and stuff")
loop = asyncio.get_event_loop()
loop.run_until_complete(beginSocket(loop))
然而,对于这段代码,等待keepAlive
后的print语句永远不会被打印。如何使代码不等待keepAlive
的结果?虽然keepAlive(socket)
会立即返回,但由于keepAlive
是一个couproutine,wait keepAlive(socket)
永远不会返回,因为keepAlive()
包含一个无限循环
不要使用wait
,而是尝试asyncio。确保将来(keepAlive(socket))
如果您确实想使用await keepAlive(socket)
,请尝试从其他地方发送您的有效负载(可能使用asyncio。事先确保将来(send\u payload(socket))
。尽管keepAlive(socket)
会立即返回,因为keepAlive
是一个常规程序,await keepAlive(socket)
将永远不会返回,因为keepAlive()
包含一个无限循环
不要使用wait
,而是尝试asyncio。确保将来(keepAlive(socket))
如果您确实想使用
wait keepAlive(socket)
,请尝试从其他地方发送您的有效负载(可能使用asyncio。事先确保将来(发送有效负载(socket))
。这是一种在同一个套接字上进行两次单独对话的情况。一个对话是你的心跳和回复信息。另一个是您正在发送的其他数据包
为此,我将保留3个独立的顶级任务(即,它们直接向事件循环报告)。我会让他们都保留对某个协调员的引用,以便他们中的任何人都可以在需要时取消所有其他人
keepAlive
函数发送
或接收
整条消息,因此它可能具有的另一项作业与此无关
这里有一种方法,你可以写这个
import asyncio
import websockets
ws=#path goes here
class RoutingTask(object):
def __init__(self, sock, defaultQueue, **kwargs):
super().__init__(**kwargs)
self.sock = sock
self.defaultQueue = defaultQueue # The queue all messages not otherwise matched go to.
self.matchers = []
async def run(self):
while True:
msg = await self.sock.recv()
msg = json.loads(msg)
matched = False
for matcher, queue in matchers:
if matcher(msg):
await queue.put(msg)
matched = True
break
if not matched:
await self.defaultQueue.put(msg)
def addMatcher(self, matcher, queue):
el = (matcher, queue)
self.matchers.append(el)
async def heartbeatTask(wssock, incomingq):
message=json.dumps({
"op": 1,
"d": 0
}) # Do this just once.
while True:
await wssock.send(message)
print("heartbeat sent")
response = await asyncio.wait_for(incomingq.get(), 10) # Wait 10 seconds for response.
assert response['op'] == 11
print("heartbeat response received.")
await asyncio.sleep(10) # Wait 10 seconds to send another heartbeat.
async def beginSocket(loop):
def heartbeatMatcher(jsondict):
return jsondict.get('op', None) == 11
async with websockets.connect(ws) as socket:
myq = asyncio.Queue(maxsize=1)
heartbeatq = asyncio.Queue(maxsize=1)
router = RoutingTask(socket, myq)
router.addMatcher(heartbeatMatcher, heartbeatq)
router = asyncio.ensure_future(router.run())
heartbeat = asyncio.ensure_future(heartbeatTask(socket, heartbeatq)
print(await myq.get())
#payloads would be sent here
print("Hey payloads being sent and stuff")
heartbeat.cancel() # Stop the heartbeat
router.cancel() # Stop the router task
loop = asyncio.get_event_loop()
loop.run_until_complete(beginSocket(loop))
这里有一些问题。如果引发异常,则心跳
和路由器
任务可能不会被取消。他们也没有真正好的方法将问题报告回主beginSocket
任务。这基本上是一种快速而肮脏的一次性演示,用来演示如何做你想做的事情
在我看来,
asyncio。确保未来
命名错误。它所做的是告诉事件循环有一个新的东西需要继续运行。它基本上是启动与线程等价的协同程序。在这种情况下,从概念上讲,您在同一个套接字上有两个单独的对话。一个对话是你的心跳和回复信息。另一个是您正在发送的其他数据包
为此,我将保留3个独立的顶级任务(即,它们直接向事件循环报告)。我会让他们都保留对某个协调员的引用,以便他们中的任何人都可以在需要时取消所有其他人
keepAlive
函数发送
或接收
整条消息,因此它可能具有的另一项作业与此无关
这里有一种方法,你可以写这个
import asyncio
import websockets
ws=#path goes here
class RoutingTask(object):
def __init__(self, sock, defaultQueue, **kwargs):
super().__init__(**kwargs)
self.sock = sock
self.defaultQueue = defaultQueue # The queue all messages not otherwise matched go to.
self.matchers = []
async def run(self):
while True:
msg = await self.sock.recv()
msg = json.loads(msg)
matched = False
for matcher, queue in matchers:
if matcher(msg):
await queue.put(msg)
matched = True
break
if not matched:
await self.defaultQueue.put(msg)
def addMatcher(self, matcher, queue):
el = (matcher, queue)
self.matchers.append(el)
async def heartbeatTask(wssock, incomingq):
message=json.dumps({
"op": 1,
"d": 0
}) # Do this just once.
while True:
await wssock.send(message)
print("heartbeat sent")
response = await asyncio.wait_for(incomingq.get(), 10) # Wait 10 seconds for response.
assert response['op'] == 11
print("heartbeat response received.")
await asyncio.sleep(10) # Wait 10 seconds to send another heartbeat.
async def beginSocket(loop):
def heartbeatMatcher(jsondict):
return jsondict.get('op', None) == 11
async with websockets.connect(ws) as socket:
myq = asyncio.Queue(maxsize=1)
heartbeatq = asyncio.Queue(maxsize=1)
router = RoutingTask(socket, myq)
router.addMatcher(heartbeatMatcher, heartbeatq)
router = asyncio.ensure_future(router.run())
heartbeat = asyncio.ensure_future(heartbeatTask(socket, heartbeatq)
print(await myq.get())
#payloads would be sent here
print("Hey payloads being sent and stuff")
heartbeat.cancel() # Stop the heartbeat
router.cancel() # Stop the router task
loop = asyncio.get_event_loop()
loop.run_until_complete(beginSocket(loop))
这里有一些问题。如果引发异常,则心跳
和路由器
任务可能不会被取消。他们也没有真正好的方法将问题报告回主beginSocket
任务。这基本上是一种快速而肮脏的一次性演示,用来演示如何做你想做的事情
在我看来,
asyncio。确保未来
命名错误。它所做的是告诉事件循环有一个新的东西需要继续运行。它基本上是启动与线程等价的协同程序。我的建议是:在尝试任何更复杂的事情之前,先理解并执行这里的示例。换句话说,从Hello World开始。:)祝你好运我的建议是理解并执行这里的示例:在尝试任何更复杂的东西之前。换句话说,从Hello World开始。:)祝你好运