首页 > 解决方案 > 使用 asyncio 同时运行的两个协程

问题描述

我正在尝试制作一个程序来读取数据以及通过 websocket 从服务器发送和接收数据。目标是创建有两个客户端灯和一个服务器的同步灯。当其中一个灯改变状态时,它会向服务器发送请求,服务器会更新另一个灯。我目前被困在客户端代码上。我可以建立到服务器的websocket连接,读取数据并将数据发送到服务器,并且可以读取轻数据。我在同时运行这两个任务时遇到问题。我想异步执行以避免竞争条件问题。我正在使用 python 3.8 和 asyncio。

到目前为止,这是我的 websocket 客户端代码:

async def init_connection(message):
  global CONNECTION_OPEN
  global CLIENT_WS
  uri = WS_URI
  async with websockets.connect(uri) as websocket:
      CONNECTION_OPEN = True
      CLIENT_WS = websocket
      # send init message
      await websocket.send(message)
      while CONNECTION_OPEN:
          await handleMessages(websocket, message)
      await websocket.send(json.dumps({'type': MessageType.Close.name, 'message': USERNAME}))
      await websocket.close()

到目前为止,这是我读到的数据代码:

async def calculate_idle(t):
  global STATE
  global prevColor
  x_arr = []
  y_arr = []
  z_arr = []
  while t >= 0:
     x, y, z = lis3dh.acceleration
     print("Current colors")
     print(accel_to_color(x,y,z))
     x_arr.append(x)
     y_arr.append(y)
     z_arr.append(z)
     newColor = accel_to_color(x,y,z)
     # remember prev color
     do_fade(prevColor, newColor)
     #strip.fill((int(a_x), int(a_y), int(a_z), 0))
     #strip.show()
     prevColor = newColor
     time.sleep(.2)
     t -= .2
  is_idle = is_lamp_idle(np.std(x_arr), np.std(y_arr), np.std(z_arr))

  if is_idle and STATE == "NOT IDLE" and CONNECTION_OPEN:
      STATE = "IDLE"
      print("Sending color")
      await asyncio.sleep(1)
  elif is_idle and CONNECTION_OPEN:
      # Check for data
      STATE = "IDLE"
      print ("Receiving data")
      await asyncio.sleep(1)
  elif is_idle and not CONNECTION_OPEN:
     print ("Idle and not connected")
      rainbow_cycle(0.001)    # rainbow cycle with 1ms delay per step
      await asyncio.sleep(1)
  else:
      STATE = "NOT IDLE"
      await asyncio.sleep(1)
      print("Is not idle")

这是应该将它们联系在一起的代码:

async def main():
    message = json.dumps({'type': "authentication", 'payload': {
                            'username': 'user1', 'secret': SHARED_SECRET}})
    loop = asyncio.get_event_loop()
    start_light = asyncio.create_task(calculate_idle(3))
    await asyncio.gather(init_connection(message), start_light)
asyncio.run(main())

还有其他功能,但前提是有一个websocket连接发送和接收数据,另一个进程读取轻数据。我还需要能够读取灯的当前状态并设置灯的当前状态,这就是我使用全局变量的原因。目前,它会读取灯,直到在计算空闲时遇到 await asyncio.sleep(1),然后切换到 websocket 代码并挂起从服务器接收数据。理想情况下,它将在读取当前状态和检查 websocket 消息之间交替。如果状态发生变化,它将发送一个 websocket 消息。

如何异步运行这两个例程并在它们之间共享数据?任何帮助表示赞赏!

标签: python-3.xasynchronouswebsocketpython-asyncio

解决方案


感谢user4815162342的评论有助于缩小问题范围。我的计算空闲没有一段时间是真的,我将 time.sleep(.2) 更改为 await asyncio.sleep(.2) 并且我能够同时从服务器和灯光读取数据。


推荐阅读