Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.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 如何运行一个不结束而不等待结果的协同程序?_Python_Python 3.x_Python Asyncio_Python 3.6 - Fatal编程技术网

Python 如何运行一个不结束而不等待结果的协同程序?

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

我有一段代码,我想连接到websocket,并通过发送心跳来保持连接的活力。在执行此操作时,我还希望能够将有效负载发送到websocket,但是我一直在等待我的
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
    函数
  • 处理通过websocket进行的其他对话的任务
  • 多路复用从websocket读取的任务
  • 多路复用任务的任务是将消息路由到适当的任务。heartbeat任务应仅获取heartbeat响应,而另一个任务应获取所有其他消息

    由于WebSocket已经对消息进行了帧处理,因此您只能
    发送
    接收
    整条消息,因此它可能具有的另一项作业与此无关

    这里有一种方法,你可以写这个

    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
    函数
  • 处理通过websocket进行的其他对话的任务
  • 多路复用从websocket读取的任务
  • 多路复用任务的任务是将消息路由到适当的任务。heartbeat任务应仅获取heartbeat响应,而另一个任务应获取所有其他消息

    由于WebSocket已经对消息进行了帧处理,因此您只能
    发送
    接收
    整条消息,因此它可能具有的另一项作业与此无关

    这里有一种方法,你可以写这个

    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开始。:)祝你好运