python - 无法设置 python 事件标志
问题描述
我整天都在为此苦苦挣扎,我很确定这是一个线程问题,但我就是不知道出了什么问题。基本上,我的 main.py 创建了一个“Neopixel”实例。那个新像素启动了一个运行 LED 环的线程。只要满足条件,一些环形动画就会运行,这与不会导致问题的简单 LED 闪烁不同。
为了处理这些情况,我使用了一个事件标志。当它是一个长动画时,它被设置为 true,当另一个 LED 状态开始时,它是未设置的,所以理论上它应该停止动画,因为它处于 while event.is_set() 循环中。但是......它永远不会被清除,即使我确实清除了它。
一些代码:
def __init__(self):
self._logger = logging.getLogger('ProjectAlice')
self._logger.info('Initializing Project Alice')
self._leds = NeoPixels()
self._leds.onStart()
....
self._logger.info('Project Alice started')
self._leds.onConnecting()
self.greetAlice()
....
elif message.topic == self._SUB_GREETING_BACK:
self._state = State.REGISTERED
self._logger.info('- Alice greeted back, module registered')
self._leds.onConnected()
我已经删除了不相关的部分,但留下了 LED 部分。如我们所见,它启动,创建一个 Neopixels 实例,为 LED 调用 onStart(),然后调用 onConnect(),然后尝试通过 mqtt 到达主服务器。当主服务器回复时,我调用 onConnected()。但 LED 始终处于“onConnect()”状态,永远不会进入“onConnected()”状态。那里有一个 print('Done') ,它从不显示,但是当我 ctrl-c 程序时,它也会执行“onConnected”动画
不知何故,
self._animation.clear()
在
def onConnected(self):
没有注册,动画循环永远不会结束,但这
self._logger.info('- Alice 回来了,模块注册')
打印,意思是 onConnected() 被调用
类 NeoPixels(对象):
def __init__(self):
self._running = True
self._ring = Adafruit_NeoPixel(num=config.settings['ringLedCount'], pin=config.settings['ringLedPin'], brightness=125, strip_type=ws.SK6812_STRIP_RGBW)
self._ring.begin()
self._queue = Queue.Queue()
self._animation = threading.Event()
threading.Thread(target=self._run).start()
def onStart(self):
self._running = True
self._animation.clear()
self._queue.put(self._start)
def onConnecting(self):
self._animation.clear()
self._queue.put(self._connecting)
def onConnected(self):
self._animation.clear()
self._queue.put(self._connected)
def _run(self):
while self._running:
func = self._queue.get()
func()
def _start(self):
for i in range(self._ring.numPixels()):
self._setPixelColorRGB(i, 255, 0, 0)
self._ring.show()
time.sleep(10 / 1000.0)
for i in range(self._ring.numPixels()):
self._setPixelColorRGB(i, 0, 0, 0)
self._ring.show()
time.sleep(10 / 1000.0)
time.sleep(0.25)
for i in range(self._ring.numPixels()):
self._setPixelColorRGB(i, 255, 0, 0)
self._ring.show()
time.sleep(1 / 1000.0)
def _connecting(self):
self._animation.set()
while self._animation.is_set():
for i in range(self._ring.numPixels()):
self._setPixelColorRGB(i, 255, 0, 0)
self._ring.show()
time.sleep(20 / 1000.0)
threading.Timer(interval=20 / 1000.0, function=self._setPixelColorRGB, args=[i, 0, 0, 0]).start()
print('done')
def _connected(self):
for i in range(self._ring.numPixels()):
self._setPixelColorRGB(i, 0, 128, 0)
self._ring.show()
time.sleep(1)
self._clear()
解决方案
这看起来很像您的队列的时间问题。如果在调用onConnected
之后调用发生得太快,onConnecting
则onConnected
在之前清除事件onConnecting
->_connecting
设置它。
这就是我剥离您的课程以运行和测试它的方式(我删除了所有 LED 环的东西并在 and 中添加了打印onConnected
语句_run
)
import time, threading, queue
class NeoPixels:
def __init__(self):
self._running = True
self._queue = queue.Queue()
self._animation = threading.Event()
threading.Thread(target=self._run)
def onStart(self):
self._running = True
self._animation.clear()
self._queue.put(self._start)
def onConnecting(self):
self._animation.clear()
self._queue.put(self._connecting)
def onConnected(self):
print("called onConnected")
self._animation.clear()
self._queue.put(self._connected)
def _run(self):
while self._running:
func = self._queue.get()
print("now running {}".format(func.__qualname__))
func()
def _start(self):
time.sleep(.5)
def _connecting(self):
self._animation.set()
while self._animation.is_set():
for i in range(5):
time.sleep(20 / 1000.0)
print('done')
def _connected(self):
for i in range(1):
print("connected")
time.sleep(1)
这是我运行它的方式:
leds = NeoPixels()
leds.onStart()
leds.onConnecting()
leds.onConnected()
这是输出:
called onConnected
now running NeoPixels._start
now running NeoPixels._connecting
如您所见,在从队列中获取并处理它onConnected
之前,它被调用并清除事件。所以当被执行时,设置事件,因为在那之后没有清除它,它会无限期地运行。_run
_start
onConnecting
_connecting
因此,更改onConnected
为等待队列清除,如下所示:
def onConnected(self):
while not self._queue.empty():
time.sleep(.1)
print("called onConnected")
self._animation.clear()
self._queue.put(self._connected)
将导致以下输出:
now running NeoPixels._start
now running NeoPixels._connecting
called onConnected
done
now running NeoPixels._connected
connected
出于好奇,您实际上如何终止/加入线程?您匿名创建它,所以我看不出您将如何处理它以在完成后关闭它。
推荐阅读
- python - ctc_loss_calculator.h:499] 未找到有效路径
- graphql - 如何使用嵌套输入 (GraphQL) 编写突变?
- macos - FFMPEG编译MacOS无法链接静态.a文件
- c# - 如何在 Unity 移动平台连接 metamask 钱包?
- apache - 为什么需要使用 http 请求标头设置限制?
- git - Gitkraken 没有列出用于克隆的 GitHub 存储库
- c# - C#Webclient 下载文件异步不起作用
- c++ - Clang 的隐式预建模块对模块实现单元无效
- unreal-engine4 - 有没有办法让用 4.27 编写的宏库在 4.26 中工作?
- mysql - 通过标准 TCP/IP 通过 SSH 将 MySQL 数据作为 Powershell 对象返回