【问题标题】:How to update global variable in asyncio create_task如何在 asyncio create_task 中更新全局变量
【发布时间】:2020-07-03 04:36:17
【问题描述】:

我目前有一个未在整个应用程序中设置的全局变量。我有两个文件,其中 file2 从 file1 导入。全局在 file1 中初始化。

这是初始化全局变量并稍后在file1中使用的代码。

import time
import asyncio

#Initialize global
CONNECTION_OPEN = False

async def calculate_idle(t):
    orig_time = t
    global CONNECTION_OPEN
    while True:
        await asyncio.sleep(5)
        print("GLOBAL CONNECTION", CONNECTION_OPEN)
        if CONNECTION_OPEN:
            print("This value is now true")
        else:
             print("Value is still false")

这是将全局设置为 true 的 websocket 代码。这位于 file2 中。

import os
import asyncio
import websockets
import json
import threading
import time
from random import randrange
from enum import Enum
from lights import calculate_idle,CONNECTION_OPEN 

async def init_connection(message):
    #Get global variable to set
    global CONNECTION_OPEN
    global CLIENT_WS
    uri = WS_URI
    async with websockets.connect(uri) as websocket:
        print("Setting Connection open to true")
        CONNECTION_OPEN = True
        CLIENT_WS = websocket
        # send init message
        await websocket.send(message)
        print("Connection is open") 
        while CONNECTION_OPEN:
            await handleMessages(websocket, message)
        await websocket.send(json.dumps({'type': MessageType.Close.name, 'message': USERNAME}))
        await websocket.close()

这是在 file2 中调用此代码的方式

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)

asyncio.run(main())

事件顺序为:

  • CONNECTION_OPEN 设置为 false
  • “将连接打开设置为真”是 印刷
  • 打印“连接已打开”
  • “值仍然为假”是 反复打印

我希望更新全局变量值,以便打印“此值现在为真”。

【问题讨论】:

  • 你可能需要展示你的导入。或者构建一个产生相同行为的minimal(自包含)示例。
  • 刚刚添加了导入。谢谢
  • 不使用全局变量,而是使用event

标签: python python-3.x python-asyncio


【解决方案1】:

只需使用asyncio.Event 对象作为全局变量。

import time
import asyncio


async def calculate_idle(t, conn_open_event):
    orig_time = t
    while True:
        await conn_open_event.wait()
        print("Connection is now open from idle")

import os
import asyncio
import websockets
import json
import threading
import time
from random import randrange
from enum import Enum
from lights import calculate_idle

async def init_connection(message, conn_open_event):
    #Get global variable to set
    global CLIENT_WS
    uri = WS_URI
    async with websockets.connect(uri) as websocket:
        print("Connection is open from socket")
        conn_open_event.set()
        CLIENT_WS = websocket
        CONNECTION_OPEN = True
        # 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 main():
    message = json.dumps({'payload': 
                            'payload')
    loop = asyncio.get_event_loop()
    event = asyncio.Event()
    start_light = asyncio.create_task(calculate_idle(3, event))
    await asyncio.gather(init_connection(message, event), start_light)

asyncio.run(main())

【讨论】:

  • 谢谢!我可能会搬到这里。
【解决方案2】:

这条线并没有像你想象的那样做:

from lights import calculate_idle,CONNECTION_OPEN 

它不会使CONNECTION_OPEN 成为lights.CONNECTION_OPEN 的别名;它将创建一个全局变量(局部于file2),并使用lights.CONNECTION_OPEN当前值进行初始化。

在模块之间共享全局的正确方法是只使用import lights(无论如何这可能是个好主意)并使用lights.CONNECTION_OPEN

更好的选择是根本不使用全局变量,而是创建一个包含共享状态的可变对象,并将其传递给需要共享它的代码。您还可以按照@gold_cy 的建议将状态添加到其他事物所需的现有对象中,例如asyncio.Event

【讨论】:

    猜你喜欢
    • 2022-09-22
    • 2013-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-20
    • 2019-06-09
    • 1970-01-01
    相关资源
    最近更新 更多