无法设置python事件标志

2024-05-15 22:31:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经为此奋斗了一整天,我很确定这是一个线程问题,但我就是不知道是怎么回事。基本上,我的主.py创建“Neopixel”的实例。neopixel启动了一个运行led环的线程。与不会引起问题的简单led闪烁不同,只要满足条件,某些铃声动画就会一直运行。你知道吗

为了处理这些条件,我使用了一个事件标志。当它是一个长的动画时,它被设置为true,当另一个led状态启动时,它被取消设置,所以理论上应该在一段时间内停止动画event.u已设置()循环。但是。。。它永远不会被清除,即使我确实清除了它。你知道吗

一些代码:

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 greeted back, module registered')

打印,表示调用onConnected()

类像素(对象):

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()

Tags: inselfforledtimequeuedef动画
1条回答
网友
1楼 · 发布于 2024-05-15 22:31:16

这看起来很像是队列的计时问题。如果对onConnected的调用在调用onConnecting之后发生得太快,onConnected会在onConnecting->;_connecting设置事件之前清除该事件。你知道吗

这就是我剥离类来运行和测试它的方式(我删除了所有的LED环,并向onConnected_run添加了print语句)

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

出于好奇,你实际上是如何终止/加入线程的?你是匿名创建的,所以我看不出一旦创建完成,你会如何控制它来关闭它。你知道吗

相关问题 更多 >