Search code examples
pythonjsonloggingrestartdisconnect

How can I get my Python Code to restart when the network disconnects


I have a piece of Python Code running as a service that pulls weather data via API.

The code itself runs perfectly fine when everything is hunky dory, ie the network, but I have noticed that sometimes the WiFi on the Pi that is pulling the API data will drop and then the python codes seems to stop.

I have a small line of code providing the most basic of logs, but I would like to improve upon it greatly. The log code just provides me with the datetime.now so I can see when the last time the code ran was.

#!/usr/bin/python3

#import modules
import cymysql
from time import sleep
from urllib.request import urlopen
import json
import datetime

#set MySQl Variables
host = "localhost"
user = "xxx"
password = "xxx"
schema = "xxx"

#connect to MySQL DB
db = cymysql.connect(host, user, password, schema)
curs = db.cursor()

#set api key for DarkSky API
apikey="xxx"
# Latitude & longitude
lati="-26.20227"
longi="28.04363"

# Add units=si to get it in sensible ISO units.
url="https://api.forecast.io/forecast/"+apikey+"/"+lati+","+longi+"?units=si"

#begin infinite loop
while True:

        #convert API reading to json and readable array 'weather'
        meteo=urlopen(url).read()
        meteo = meteo.decode('utf-8')
        weather = json.loads(meteo)

        #set variables for current weather
        cTemp = (weather['currently']['temperature'])
        cCond = (weather['currently']['summary'])
        cRain1 =  (weather['currently']['precipProbability'])
        cRain2 = cRain1*100
        cIcon = (weather['currently']['icon'])
        oaSum = (weather['daily']['summary'])

        #print variables - for testing purposes
        #print (cTemp)
        #print (cCond)
        #print (cRain2)
        #print (cIcon)
        #print (oaSum)

        #extract daily data from 'weather' array
        daily = (weather['daily']['data'])

        #create new arrays for daily variables
        listHigh = []
        listLow = []
        listCond = []
        listRain = []
        listIcon = []

        #set daily variables
        for i in daily:
                listHigh.append(i['temperatureHigh'])

        for i in range(0,len(listHigh)):
                high1 = listHigh[0]
                high2 = listHigh[1]
                high3 = listHigh[2]
                high4 = listHigh[3]
                high5 = listHigh[4]
                high6 = listHigh[5]
                high7 = listHigh[6]
                high8 = listHigh[7]

        for o in daily:
                listLow.append(o['temperatureLow'])

        for o in range(0,len(listLow)):
                low1 = listLow[0]
                low2 = listLow[1]
                low3 = listLow[2]
                low4 = listLow[3]
                low5 = listLow[4]
                low6 = listLow[5]
                low7 = listLow[6]
                low8 = listLow[7]

        for p in daily:
                listCond.append(p['summary'])

        for p in range(0,len(listCond)):
                cond1 = listCond[0]
                cond2 = listCond[1]
                cond3 = listCond[2]
                cond4 = listCond[3]
                cond5 = listCond[4]
                cond6 = listCond[5]
                cond7 = listCond[6]
                cond8 = listCond[7]

        for m in daily:
                listRain.append(m['precipProbability'])

        for m in range(0,len(listRain)):
                rain1 = listRain[0]
                rain2 = listRain[1]
                rain3 = listRain[2]
                rain4 = listRain[3]
                rain5 = listRain[4]
                rain6 = listRain[5]
                rain7 = listRain[6]
                rain8 = listRain[7]

        #convert rain chance to readable percentage
        prain1 = rain1*100
        prain2 = rain2*100
        prain3 = rain3*100
        prain4 = rain4*100
        prain5 = rain5*100
        prain6 = rain6*100
        prain7 = rain7*100
        prain8 = rain8*100

        for l in daily:
                listIcon.append(l['icon'])

        for l in range (0,len(listIcon)):
                icon1 = listIcon[0]
                icon2 = listIcon[1]
                icon3 = listIcon[2]
                icon4 = listIcon[3]
                icon5 = listIcon[4]
                icon6 = listIcon[5]
                icon7 = listIcon[6]
                icon8 = listIcon[7]

        #print daily variables - for testing purposes
        #print (high1)
        #print (low1)
        #print (cond1)
        #print (prain1)
        #print (icon1)
        #print (high2)
        #print (low2)
        #print (cond2)
        #print (prain2)
        #print (icon2)

        #update data in DataBase
        try:
                sql_update_query = """UPDATE weather SET current_temp = %s, cur$
                varis = (cTemp, cCond, cRain2, cIcon, high1, low1, cond1, prain$
                curs.execute(sql_update_query, varis)
                db.commit()
        except db.Error as error:
                print("Error: {}".format(error))
                db.rollback()

        #write date to log file
        with open ("/home/pi/CoRo/Projects/WeatherMan/weatherlog.txt", mode="w") as file:
                file.write('Last Data was pulled at: %s' %(datetime.datetime.now()))
        #set loop to sleep for 10 minutes and go again
        sleep(600)

I understand that the Database Code is snipped, but it is just the variables being put in to the database, which I can see works.

However if the network disconnects, the code stops and the database is left with the last polled API data.

How would I restart the python code if the API get fails?

Thanks in advance,


Solution

  • You could rewrite the portion of your code that pulls the weather data as a function or separate module. This would allow you to call it only when the network connection is working. Some pseudo code below:

    if network_connection:
        pull_weather_data()
    else:
        do_something()
    

    do_something() could be an effort to reconnect to the network, such as resetting your network adapter.

    You could determine the state of the network connection by trying to ping your router or an external IP like one of Google's DNS server (8.8.8.8 or 8.8.4.4).

    To avoid nested loops you could use the continue clause. For example:

    while True:
        if network_connection:
            pull_weather_data()
        else:
            reset_network_connection()
            time.sleep(180) # Sleep for 3 minutes.
            continue
    

    The continue will send the interpreter back to the start of the while loop. From there it will check the network connection and either pull data or reset the network connection and sleep for another 3 minutes.