Running two concurrent infinite loops using asyncio

huangapple go评论58阅读模式
英文:

Running two concurrent infinite loops using asyncio

问题

我有一个程序,正在接收家庭气象站传输的UDP数据。其中有一个数值叫做"rain_accum",表示过去一分钟的总雨量累积。当"rain_accum" > 0时,我希望灯光闪烁。当"rain_accum" == 0时,我希望它不闪烁。

我对Python相当新,对uasyncio非常陌生(注意:我正在使用Micropython,因此可能没有asyncio的所有功能),而且我感到很困惑。我已经花了3天的时间来研究这个问题,实际上已经很接近让它工作了,但闪烁的时间明显偏差很大,需要好几秒,而且会错过UDP消息。我将代码简化为我一直试图做的基本要点,希望能得到一些关于接下来怎么做的方向。

import uasyncio

async def blink():
    while True:
        print("Here 1")
        await uasyncio.sleep(1)
        print("Here 2")
        await uasyncio.sleep(1)
        
async def getData():
    
    while True:
        print("Getting data")
        
        if True:
            await blink()
        print("Next loop")
        await uasyncio.sleep(5)
        
try:
    
    uasyncio.run(getData())
    
except KeyboardInterrupt:
    print("Quitting")

你提供的代码包含了两个异步函数blink()getData(),以及主程序的入口点。blink()函数是一个无限循环,每隔1秒打印一些消息。getData()函数也是一个无限循环,每隔5秒打印一些消息,并在条件if True下调用了blink()函数。

你的问题是关于如何实现基于"rain_accum"值的灯光闪烁,但在提供的代码中,这部分逻辑还没有被包含进去。你需要在getData()函数中添加读取"rain_accum"值的逻辑,并根据其值来决定是否调用blink()函数。

请提供关于"rain_accum"值的更多信息,以便我可以帮助你添加相应的逻辑。

英文:

I've got a program that is pulling UPD data being transmitted by my home weather station. One of those values that is a "rain_accum" which is the total rain accumulation in the past minute. When that "rain_accum" is > 0, I want the light to blink. When the rain_accum == 0, I want it to not blink.

I'm fairly new to Python and very new to uasyncio (note: I'm using Micropython, so I may not have all the capablities of asyncio) and I'm just getting lost. I've been messing with this for 3 days and have actually gotten pretty close to getting it working, but the timing was way off the blink would take several seconds and UDP messages were getting missed. I've cut my code back to the bare basics of what I've been trying to do hoping I could get some direction as to where to go with this.

import uasyncio

async def blink():
    while True:
        print("Here 1")
        await uasyncio.sleep(1)
        print("Here 2")
        await uasyncio.sleep(1)
        
async def getData():
    
    while True:
        print("Getting data")
        
        if True:
            await blink()
        print("Next loop")
        await uasyncio.sleep(5)
        
                              
try:
    
    uasyncio.run(getData())
    
except KeyboardInterrupt:
    print("Quitting")

答案1

得分: 1

在你的问题中的示例中,一旦调用await blink(),你就永远不会返回:你当前的协程已经进入了一个无限循环。

看一下文档中的示例,它展示了如何同时启动两个协程。如果我们将这个示例与你问题中的示例结合起来,可能会得到类似以下的内容:

import random
import time
import uasyncio

blink_active = False

async def blink():
    while True:
        if blink_active:
            print("Here 1")
            await uasyncio.sleep(1)
            print("Here 2")
            await uasyncio.sleep(1)
        else:
            await uasyncio.sleep(1)

async def getData():
    global blink_active

    # 启动一个并发的异步任务
    uasyncio.create_task(blink())

    last_check = 0
    while True:
        now = time.time()
        if now - last_check > 5:
            data = random.randint(0, 10)
            print("Got data", data)
            if data > 7:
                print("Start blinking")
                blink_active = True
            else:
                print("Stop blinking")
                blink_active = False
            last_check = now

        print("Next loop")
        await uasyncio.sleep(1)

try:
    uasyncio.run(getData())
except KeyboardInterrupt:
    print("Quitting")

在这里,getData() 启动一个会永远运行的 blink 任务。它是否会"闪烁"(或打印文本)由全局变量 blink_active 控制。

getData 中,我们的循环每秒运行一次,但我们每五秒才收集新数据。根据从我们的"传感器"中获取的值,我们通过适当设置 blink_active 来启动或停止闪烁。

英文:

In the example in your question, once you call await blink() you never return: your current coroutine has entered an infinite loop.

Take a look at the example from the documentation, which shows how to start two coroutines concurrently. If we were to take that examples and fit it to the example from your question, we might get something like:

import random
import time
import uasyncio

blink_active = False


async def blink():
    while True:
        if blink_active:
            print("Here 1")
            await uasyncio.sleep(1)
            print("Here 2")
            await uasyncio.sleep(1)
        else:
            await uasyncio.sleep(1)


async def getData():
    global blink_active

    # Start a concurrent async task
    uasyncio.create_task(blink())

    last_check = 0
    while True:
        now = time.time()
        if now - last_check > 5:
            data = random.randint(0, 10)
            print("Got data", data)
            if data > 7:
                print("Start blinking")
                blink_active = True
            else:
                print("Stop blinking")
                blink_active = False
            last_check = now

        print("Next loop")
        await uasyncio.sleep(1)


try:
    uasyncio.run(getData())
except KeyboardInterrupt:
    print("Quitting")

Here, getData() starts a blink task that will run forever. Whether it "blinks" (or prints out text) is controlled by a global variable, blink_active.

In getData, our loop runs once/second, but we only gather new data every five seconds. Depending on the value we retrieve from our "sensor", we start or stop the blinker by setting blink_active appropriately.

huangapple
  • 本文由 发表于 2023年2月10日 03:11:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75403360.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定