使用asyncio和contextvars在python中的两个异步程序之间共享状态

使用asyncio和contextvars在python中的两个异步程序之间共享状态,python,python-3.x,python-asyncio,python-contextvars,Python,Python 3.x,Python Asyncio,Python Contextvars,我目前正在运行两个无限异步任务,并希望在它们之间共享状态。一个任务是websocket连接,它读入消息然后发送消息,另一个读取传入的灯光数据。我想在两个任务之间发送一个布尔值,表示websocket连接是否成功 下面是我初始化上下文的方式 client_connect_var = contextvars.ContextVar('client_connect',default = False) client_connect_var.set(False) ctx = contextvars.copy

我目前正在运行两个无限异步任务,并希望在它们之间共享状态。一个任务是websocket连接,它读入消息然后发送消息,另一个读取传入的灯光数据。我想在两个任务之间发送一个布尔值,表示websocket连接是否成功

下面是我初始化上下文的方式

client_connect_var = contextvars.ContextVar('client_connect',default = False)
client_connect_var.set(False)
ctx = contextvars.copy_context()
async def main():
  message = json.dumps({'payload': {
                        'payload'})
  loop = asyncio.get_event_loop()
  start_light = asyncio.create_task(calculate_idle(3))
  await asyncio.gather(init_connection(message), start_light)

ctx.run(asyncio.run(main()))
以下是我在init_连接中的代码:

async def init_connection(message):
  async with websockets.connect(uri) as websocket:
      #This should set the global context variable to true
      client_connect_var.set(True)
      CLIENT_WS = websocket
      client_connect = client_connect_var.get()
    # send init message
    await websocket.send(message)
    print("Connection is open")
    while client_connect:
        await handleMessages(websocket, message)
    await websocket.close()
这里是它试图在光代码中获取当前状态的地方

async def calculate_idle(t):
    orig_time = t
    while True:
        await asyncio.sleep(5)
        #This should be true, but it's false
        client_connect = client_connect_var.get()
        await asyncio.sleep(5)

在calculate_idle中,上下文中的变量仍然设置为false。我不知道如何从init_连接内部将其设置为true。我想将此扩展到更新状态中的其他值,这些值是对象。任何帮助都将不胜感激

ContextVar
与您试图使用它的目的相反:它用于任务的局部数据,类似于“任务局部”全局变量


要在两个任务之间共享数据,您可以使用普通的Python共享机制,例如全局变量或普通可变值(例如dict或您选择的类的实例)。您还可以使用同步,如
asyncio.Event
(),在值更改时通知其他任务。

您可以将代码减少到反映所发生情况所需的最小数量吗?是的,我会减少一点。为什么要使用
ctx=contextvars.copy_context()
然后使用
ctx.run(asyncio.run(main())
?我以为我是在用变量复制原始上下文,然后在复制的上下文中运行main。当我尝试使用全局变量时,我遇到了相同的问题,即它没有更新。我不确定是否使用asyncio.create_任务将其置于不同的上下文中?全局变量似乎是最初设置的,然后在init_连接中更改,但仍然是calculate_idle中的初始值。@avenmia您是否正确更新了该变量?您是否使用
print
s检查代码是否实际执行?这样的事情应该是可行的,asyncio(在那个级别)并没有什么神奇的东西会阻止这种状态共享工作。我只是恢复到使用全局变量,并使用prints检查它是否正在执行,是否正确。首先,将全局变量初始化为false,在init_连接中,我使用global关键字获取变量。连接后,我打印(“连接设置为true”),并将全局设置为true。在calculate_idle中,我打印全局变量的状态,但它仍然为false。@很好,我想编辑问题和发布新问题都是有效的方法,所以这取决于您。事实很可能证明,真正的问题在代码的其他地方。@avenmia Python的全局变量实际上是模块局部变量;请看我对另一个问题的回答。