Python Forum

Full Version: Infinite loop problem
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello all I am looking for help with a simple python3 code that I am using for taking dht22 sensor readings and logging them for influxdb and grafana (works great by the way), My problem is that the code will run for a random amount of time then just stops, Im sure its from a dht read error but I need it to keep running regardless of a read error. If someone could take my code and fix it (show me where or whats missing) I would be much appreciative :)

import time 
import logging
import Adafruit_DHT as adht

logging.basicConfig(filename='temperature.log', filemode='a', format='%(created)f %(message)s', level=logging.INFO) 

try:

    while True:     
        h,t = adht.read_retry(adht.DHT22, 23)     
        logging.info('Temp={0:0.1f} C and Humidity={1:0.1f} %'.format(t, h))
        
        
# Wait for * seconds
        print("Waiting for 60 seconds… Sensor 0")
        time.sleep(60)
    else:
        print("Failed to retrieve data from DHT22 sensor")
        print('------------------------------------')
        time.sleep(60) # Delay in seconds.

except:KeyboardInterrupt
pass
Why don't you just catch all exceptions?

If its a ReadError then it will just continue to loop?
How do I go about catching all exceptions?
Based on just reading the code:

else: part of while True: loop is redundant. Nothing in while-loop body sets condition False so else-clause can't be executed. From documentation:


Output:
The "while" statement is used for repeated execution as long as an expression is true: while_stmt ::= "while" assignment_expression ":" suite ["else" ":" suite] This repeatedly tests the expression and, if it is true, executes the first suite; if the expression is false (which may be the first time it is tested) the suite of the "else" clause, if present, is executed and the loop terminates.
So only way out from while True is exception raised during execution of loop. If such event occurs in try: block then KeyboardInterrupt is raised. From documentation:

Output:
The "except" clause(s) specify one or more exception handlers. When no exception occurs in the "try" clause, no exception handler is executed. When an exception occurs in the "try" suite, a search for an exception handler is started. This search inspects the except clauses in turn until one is found that matches the exception. An expression- less except clause, if present, must be last; it matches any exception. /../ When a matching except clause is found, the exception is assigned to the target specified after the "as" keyword in that except clause, if present, and the except clause’s suite is executed. All except clauses must have an executable block. When the end of this block is reached, execution continues normally after the entire try statement.
So 'catch it all' except: clause catches any error raised in try block just to raise KeyboardInterrupt.
Thanks for the help dudes :)
If you compare the old Library and the new from Circuit Python, you see that they raise a RuntimeError if something wrong happens.

https://github.com/adafruit/Adafruit_Cir...ht.py#L205
https://github.com/adafruit/Adafruit_Cir...ht.py#L209
https://github.com/adafruit/Adafruit_Cir...ht.py#L237
https://github.com/adafruit/Adafruit_Cir...ht.py#L241

The old library is also raises a RuntimeError: https://github.com/adafruit/Adafruit_Pyt...erry_Pi.py (just seek "raise ")

Corrected version, but not tested.

import logging
import sys
import time

import Adafruit_DHT as adht

logging.basicConfig(
    filename="temperature.log",
    filemode="a",
    format="%(created)f %(message)s",
    level=logging.INFO,
)
log = logging.getLogger()


def main_loop():
    while True:
        try:
            humidity, temperature = adht.read_retry(adht.DHT22, 23)
        except RuntimeError as e:
            # this block, if RuntimeError were raised from adht.read_retry
            log.error(f"RuntimeError: {e}")
        else:
            # this block, if no Exception were raised by adht.read_retry
            log.info(f"Temp={temperature:0.1f} C and Humidity={humidity:0.1f} %")
        # this is always executed
        print("Waiting for 60 seconds… Sensor 0", file=sys.stderr)
        time.sleep(60)


if __name__ == "__main__":
    try:
        main_loop()
    except KeyboardInterrupt:
        print("\nCTRL+C\n", file=sys.stderr)
By the way, I use always black and isort for code formatting and sorting of imports.

For example the module from Adafruit is a third-party module. This should be imported after first party packages like sys, os, etc.

Other changes:
  • f-strings
  • log = logging.getLogger() and use this instead of logging.error, logging.info
  • printing to sys.stderr
  • loop is in a function
  • try-except around main_loop