来自内部的异步任务无法更改全局 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
我是运行一个收集系统(监控)信息的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