I’m working on putting together an application for Raspberry Pi 3. I have experience in other languages but Python has never been a favorite of mine, thus haven’t used it much.
The threading portion involves serial communication and queuing both input and output. I’ve successfully put together a small stand-alone script that successfully does everything I want.
The problem is converting this to a class, as I haven’t yet found a way to successfully kill the threads I’ve started there. The parts I’ve written seem to work the same as the stand-alone script I made first. Using a flag to indicate when to terminate the threads worked there but doesn’t seem to in the class. Is this a scoping thing? I thought I tried using a global as well, but it may be my ignorance of the language nuances creeping in.
I’m looking for either a way to restructure this achieving the same effect, or (better) just a way to stop the threads.
The script for testing the class is very simple, with a few things I’ve tried commented out:
foo = bar.Bar() #time.sleep(5) #foo.stop() #del foo #exit()
Trying to whittle down the class to the relevant essentials (always tough to do…):
import time import threading import serial import queue global main_running class Bar(object): ### A bunch of constants here def __init__(self, com_port='/dev/ttyS0'): global main_running self._serial_rx_queue = queue.Queue() self._serial_tx_queue = queue.Queue() self._foobar_port = serial.Serial( port = com_port, baudrate = 14400, parity = serial.PARITY_NONE, stopbits = serial.STOPBITS_ONE, bytesize = serial.EIGHTBITS, timeout = 1 ) main_running = True #self._main_running = True self._ping_thread = threading.Thread(target=self._ping_task) self._serial_rx_thread = threading.Thread(target=self._serial_rx_task) self._serial_tx_thread = threading.Thread(target=self._serial_tx_task) self._ping_thread.start() self._serial_rx_thread.start() self._serial_tx_thread.start() ###### NOT WORKING - THREADS NEVER DIE! def stop(self): global main_running self._foobar_port.close() main_running = False #self._main_running = False self._serial_tx_thread.join() self._serial_rx_thread.join() self._ping_thread.join() ###### ALSO NOT WORKING - THREADS NEVER DIE! # # Destructor # def __del__(self): # self._foobar_port.close() # self._main_running = False # # self._serial_tx_thread.join() # self._serial_rx_thread.join() # self._ping_thread.join() ### A bunch of application specific message encoding/decoding def _serial_rx_task(self): global main_running while(self._foobar_port.isOpen() and (main_running == True)): if(self._foobar_port.in_waiting): if(self._foobar_port.isOpen()): response = self._foobar_port.readline() ### Application specific code to process data read time.sleep(0.01) def _serial_tx_task(self): global main_running while(self._foobar_port.isOpen() and (main_running == True)): while(self._serial_tx_queue.empty() and (main_running == True)): time.sleep(0.01) message = self._serial_tx_queue.get() print('>>> ', message) if(self._foobar_port.isOpen()): self._foobar_port.write(message) time.sleep(0.1) def _ping_task(self): global main_running # while self._main_running: while main_running == True: self._serial_tx_queue.put('dummy message for illustration') time.sleep(1) ```