我正在尝试使用threading.Thread与Celery一起工作就像一个守护进程。在更大的范围内,线程将轮询硬件传感器作为基于Web UI的恒温器的一部分,但是缩小了,这是我坚持的一点:
from celery import Celery
from celery.signals import worker_init
from celery.signals import worker_process_shutdown
from threading import Thread
from threading import Event
from time import sleep
class ThisClass(object):
def __init__(self):
self.shutdown = Event()
self.thread = Thread(target=self.BackgroundMethod)
def Start(self):
self.thread.start()
def Stop(self):
self.shutdown.set()
def BackgroundMethod(self):
while not self.shutdown.is_set():
print("Hello, world!")
sleep(1)
this_class = ThisClass()
celery_app = Celery("tasks", broker="amqp://guest@localhost//")
@worker_init.connect
def WorkerReady(**kwargs):
this_class.Start()
@worker_process_shutdown.connect
def StopPollingSensors(**kwargs):
this_class.Stop()
这个Celery脚本应该创建一个ThisClass实例作为this_class,并在Celery启动时运行this_class.Start()。当Celery关闭时,它应该调用this_class.Stop(),它优雅地退出ThisClass中的Thread并且Celery干净地退出。
但是,当我在Celery中按Ctrl-C发出SIGINT信号时,即使发出多个SIGTERM,此_class的线程也会继续运行并且Celery不会退出。令我困惑的是,如果我在ThisClass.Stop中打印一个print语句,我就会看到它。此外,如果我在sleep(5); this_class.Stop()
之后添加this_class.Start()
,则线程会按预期启动和停止,并且Celery将在发出SIGINT时正常退出。
我应该如何在基于Celery的脚本中终止threading.Thread实例?
答案 0 :(得分:0)
考虑在外部创建Event
对象,并将其传递给Thread
子类。线程在事件对象上循环。当外部函数调用Event.set()
时,线程循环会完全退出while
循环。
import sys, time
from threading import Event, Thread, Timer
class ThisClass2(Thread):
def __init__(self, event):
super(ThisClass2,self).__init__()
self.event = event
def run(self):
print 'thread start'
while not self.event.wait(timeout=1.0):
print("thread: Hello, world!")
print 'thread done'
event2 = Event()
x = ThisClass2(event2)
x.start()
print 'okay'
time.sleep(1)
print 'signaling event'
event2.set()
print 'waiting'
x.join()
示例输出:
thread start
okay
thread: Hello, world!
signaling event
waiting
thread done