英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论