来自内部的异步任务无法更改全局 INT 但可以更改 LIST

asyncio task from within cannot change global INT but can change LIST

我是运行一个收集系统(监控)信息的asyncio任务。我喜欢将一个值传递给一个变量,以便在另一个任务中使用。 我不是等待和返回值,而是喜欢保留任务运行。 当我使用列表但不适用于浮点数或 INT 时它有效。非常感谢任何帮助

cpuList = [1]
teststore = 0

sync def data_collect(delay):
    while True:
        cpu_val = psutil.cpu_percent(interval=0)
        teststore = cpu_val
        cpuList.append(cpu_val)
        print(f'from within {teststore}')
        await asyncio.sleep(1)
        time.sleep(delay)

async def main():  
    task1 = asyncio.create_task(data_collect(1))
    while True:
        print(f'from main {cpuList}')
        print(f'from main {teststore}') 
        time.sleep(1)

## output:
# from within 16.9
# from main [1, 16.9]
# from main 0
# from within 2.9
# from main [1, 16.9, 2.9]
# from main 0
# from within 1.3
# from main [1, 16.9, 2.9, 1.3]
# from main 0

您缺少 data_collect 函数中的 global teststore

在 Python 中,您必须使用 global 关键字(或 nonlocal 用于嵌套函数)以便 分配 给一个名称在 global/non-local 范围内定义。

cpuList.append(cpu_val) 有效,因为您没有分配给 cpuList 名称,而是在名称 cpuList 分配给的对象上调用方法。 (cpuList = cpuList + [cpu_val] 无效。)

除此之外,您可能要考虑完全不使用全局变量,而是将对象传递给 data_collect 函数:

async def data_collect(delay, values):
    while True:
        cpu_val = psutil.cpu_percent(interval=0)
        values.append(cpu_val)
        await asyncio.sleep(delay)


async def main():
    values = []  # modified by the async task
    task1 = asyncio.create_task(data_collect(1, values))
    while True:
        print(values)
        time.sleep(1)

此外,考虑到这两个协同程序可能不会 运行 完美同步,这也开启了使用 Event 进行同步的能力:

import asyncio


async def data_collect(delay: float, values: list, signal: asyncio.Event):
    while True:
        cpu_val = psutil.cpu_percent(interval=0)
        values.append(cpu_val)
        await asyncio.sleep(delay)
        signal.set()


async def main():
    values = []  # modified by the async task
    signal = asyncio.Event()
    task1 = asyncio.create_task(data_collect(1, values, signal))
    while True:
        await signal.wait()  # wait until the other task informs it has new data
        signal.clear()
        print(values)

编辑

如果您确实确实还需要修改一个整数,则需要将其“装箱”到例如一个 class 实例:

class CollectedData:
    def __init__(self):
        self.cpu_value = 0
        self.values = []
 

async def data_collect(delay, collected_data):
    while True:
        cpu_val = psutil.cpu_percent(interval=0)
        collected_data.cpu_value = cpu_val
        collected_data.values.append(cpu_val)
        await asyncio.sleep(delay)


async def main():
    cd = CollectedData()
    task1 = asyncio.create_task(data_collect(1, cd))
    while True:
        print(cd.cpu_value, cd.values)
        time.sleep(1)  # or other synchronization