How To Terminate A Thread In Python?
I know the topic has been covered a few times however I have attempted, or at least tried virtually all solutions however being a fairly new python basher I've not been able to get
Solution 1:
Your t1
variable is a local, so it gets lost when you exit the on_message
function. Also, you're conflating the class task
and the instance t1
(task.stop()
won't work).
For a quick fix, declare t1 = None
as a global, then add global t1
to your on_message
function...
However, I'd consider refactoring things so there's an always-running thread to command the Blinkt!, and the MQTT message handler simply sets its state accordingly – something like this. Dry-coded, obviously, so there may be some silliness.
from sys import exit
import blinkt
import threading
import time
MQTT_SERVER = "192.168.x.x"
MQTT_PORT = 1883
MQTT_TOPIC = "mytopic"
REDS = [0, 0, 0, 0, 0, 16, 64, 255, 64, 16, 0, 0, 0, 0, 0, 0]
start_time = time.time()
classBlinktManager(threading.Thread):
def__init__(self):
threading.Thread.__init__(self)
self.stop_event = threading.Event()
self.mode = Nonedefrun(self):
whilenot self.stop_event.isSet():
self.tick()
self.stop_event.wait(0.1) # instead of sleepdeftick(self):
if self.mode == "reds":
self._tick_reds()
def_tick_reds(self):
delta = (time.time() - start_time) * 16
offset = int(
abs((delta % len(REDS)) - blinkt.NUM_PIXELS)
)
for i inrange(blinkt.NUM_PIXELS):
blinkt.set_pixel(i, REDS[offset + i], 0, 0)
blinkt.show()
defclear(self):
self.mode = None
blinkt.clear()
blinkt.show()
defset_all_pixels(self, r, g, b):
self.mode = Nonefor x inrange(blinkt.NUM_PIXELS):
blinkt.set_pixel(x, r, g, b)
blinkt.show()
defset_pixel(self, x, r, g, b):
self.mode = None
blinkt.set_pixel(x, r, g, b)
blinkt.show()
defbegin_reds(self):
self.mode = "reds"defon_connect(client, userdata, flags, rc):
print("Connected with result code " + str(rc))
client.subscribe(MQTT_TOPIC)
defon_message(client, userdata, msg):
data = msg.payload
iftype(data) isbytes:
data = data.decode("utf-8")
data = data.split(",")
command = data.pop(0)
if command == "clr"andlen(data) == 0:
blinkt_manager.clear()
if command == "rgb"andlen(data) == 4:
x = data[0]
r, g, b = [int(x) & 0xFFfor x in data[1:]]
if x == "*":
blinkt_manager.set_all_pixels(r, g, b)
else:
# TODO: error handling
blinkt_manager.set_pixel(int(x), r, g, b)
if command == "mtg"andlen(data) == 0:
blinkt_manager.begin_reds()
blinkt.set_clear_on_exit()
blinkt_manager = BlinktManager()
blinkt_manager.start()
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(MQTT_SERVER, MQTT_PORT, 60)
client.loop_forever()
Solution 2:
Python program raising exceptions in a python thread
import threading
import ctypes
import time
classthread_with_exception(threading.Thread):
def__init__(self, name):
threading.Thread.__init__(self)
self.name = name
defrun(self):
# target function of the thread class try:
whileTrue:
print('running ' + self.name)
finally:
print('ended')
defget_id(self):
# returns id of the respective thread ifhasattr(self, '_thread_id'):
return self._thread_id
forid, thread in threading._active.items():
if thread is self:
returniddefraise_exception(self):
thread_id = self.get_id()
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,
ctypes.py_object(SystemExit))
if res > 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
print('Exception raise failure')
t1 = thread_with_exception('Thread 1')
t1.start()
time.sleep(2)
t1.raise_exception()
t1.join()
Post a Comment for "How To Terminate A Thread In Python?"