python-3.xexceptionsignalsraspberry-pi3gpiozero

python hangs even with exception handling


I've got a raspberry PI attached to a MCP3008 ADC which is measuring an analog voltage across a thermistor. I'm using the gpiozero python library for communication between the PI and ADC. My code below runs for several minutes and then spits out an error, and then hangs on function get_temp_percent. That function returns the average of five measurements from the ADC. I'm using Signal to throw an exception after 1 second of waiting to try to get past the hang, but it just throws an error and hangs anyway. It looks like nothing in my except statement is being read. Why am I not escaping the code hang?

import time
from gpiozero import MCP3008
from math import log
import pymysql.cursors
from datetime import datetime as dt
import signal 
import os


def handler(signum, frame):
    print('Signal handler called with signal', signum, frame)
    raise Exception("Something went wrong!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")   


def get_temp_percent(pos=0):
    x=[]
    for i in range(0,5):
        while True:
            try:
                signal.signal(signal.SIGALRM, handler)
                signal.alarm(1)
                adc = MCP3008(pos)
                x.append(adc.value)
                #adc.close()
            except Exception as inst:
                print('get_temp_percent {}'.format(inst) )
                signal.alarm(0)
                continue
            break
        signal.alarm(0)
        time.sleep(.1)
    return round(sum(x)/len(x),5)


def write_date(temp0):
    <writes temp0 to mysql db >        

# Connect to the database
connection = pymysql.connect(host='', user='', password='', db='',cursorclass = pymysql.cursors.DictCursor)

while True:        
    temp_percent = get_temp_percent()
    print('Temp Percent = {}'.format(temp_percent) )

    <some function that do some arithmetic to go temp_percent to temp0>

    write_date(temp0)
    print('Data Written')

    time.sleep(1)
    print('Sleep time over')
    print('')

Function get_temp_percent causes the problem below

Signal handler called with signal 14 <frame object at 0x76274800>
Exception ignored in: <bound method SharedMixin.__del__ of SPI(closed)>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 137, in __del__
    super(SharedMixin, self).__del__()
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 122, in __del__
    self.close()
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 82, in close
    old_close()
  File "/usr/lib/python3/dist-packages/gpiozero/pins/local.py", line 102, in close
    self.pin_factory.release_all(self)
  File "/usr/lib/python3/dist-packages/gpiozero/pins/__init__.py", line 85, in release_all
    with self._res_lock:
  File "/home/pi/Desktop/testing exceptions.py", line 13, in handler
    raise Exception("Something went wrong!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
Exception: Something went wrong!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Solution

  • It looks like your call to gpiozero does a lot of work behind the scenes. When your exception is processed, the library is trying to clean up and gets stuck.

    I took a quick look at the docs for the library and it looks like you may be able to keep hold of the pins so you can re-use them.

    e.g.

    import ...
    
    adcs = {}
    
    def get_adc_value(pos):
        if pos not in adcs:
            adcs[pos] = MCP3008(pos)
        return adcs[pos].value
    
    def get_temp_percent(pos=0):
        x = []
        for i in range(0, 5):
            x.append(get_adc_value(pos))
            time.sleep(.1)
        return round(sum(x)/len(x),5)
    
    while True:
       temp_percent = get_temp_percent()
       ...