How to keep a program running if there is an Traceback error

Question:

I made a simple script for amusment that takes the latest comment from http://www.reddit.com/r/random/comments.json?limit=1 and speaks through espeak. I ran into a problem however. If Reddit fails to give me the json data, which it commonly does, the script stops and gives a traceback. This is a problem, as it stops the script. Is there any sort of way to retry to get the json if it fails to load. I am using requests if that means anything

If you need it, here is the part of the code that gets the json data

url = 'http://www.reddit.com/r/random/comments.json?limit=1'
r = requests.get(url)
quote = r.text
body = json.loads(quote)['data']['children'][0]['data']['body']
subreddit = json.loads(quote)['data']['children'][0]['data']['subreddit']
Asked By: Dolphman

||

Answers:

For the vocabulary, the actual error you’re having is an exception that has been thrown at some point in a program because of a detected runtime error, and the traceback is the program thread that tells you where the exception has been thrown.

Basically, what you want is an exception handler:

try:
    url = 'http://www.reddit.com/r/random/comments.json?limit=1'
    r = requests.get(url)
    quote = r.text
    body = json.loads(quote)['data']['children'][0]['data']['body']
    subreddit = json.loads(quote)['data']['children'][0]['data']['subreddit']
except Exception as err:
    print err

so that you jump over the part that needs the thing that couldn’t work. Have a look at that doc as well: HandlingExceptions – Python Wiki

As pss suggests, if you want to retry after the url failed to load:

done = False
while not done:
    try:
        url = 'http://www.reddit.com/r/random/comments.json?limit=1'
        r = requests.get(url)
    except Exception as err:
        print err
    done = True
quote = r.text
body = json.loads(quote)['data']['children'][0]['data']['body']
subreddit = json.loads(quote)['data']['children'][0]['data']['subreddit']

N.B.: That solution may not be optimal, since if you’re offline or the URL is always failing, it’ll do an infinite loop. If you retry too fast and too much, Reddit may also ban you.

N.B. 2: I’m using the newest Python 3 syntax for exception handling, which may not work with Python older than 2.7.

N.B. 3: You may also want to choose a class other than Exception for the exception handling, to be able to select what kind of error you want to handle. It mostly depends on your app design, and given what you say, you might want to handle requests.exceptions.ConnectionError, but have a look at request’s doc to choose the right one.

Here’s what you may want, but please think this through and adapt it to your use case:

import requests
import time
import json

def get_reddit_comments():
    retries = 5
    while retries != 0:
        try:
            url = 'http://www.reddit.com/r/random/comments.json?limit=1'
            r = requests.get(url)
            break  # if the request succeeded we get out of the loop
        except requests.exceptions.ConnectionError as err:
            print("Warning: couldn't get the URL: {}".format(err))
            time.delay(1) # wait 1 second between two requests
            retries -= 1
            if retries == 0: # if we've done 5 attempts, we fail loudly
                return None
    return r.text
  
def use_data(quote):
    if not quote:
        print("could not get URL, despites multiple attempts!")
        return False
    
    data = json.loads(quote)        

    if 'error' in data.keys():
        print("could not get data from reddit: error code #{}".format(quote['error']))
        return False
    
    body = data['data']['children'][0]['data']['body']
    subreddit = data['data']['children'][0]['data']['subreddit']

    # … do stuff with your data here

if __name__ == "__main__":
    quote = get_reddit_comments()
    if not use_data(quote):
        print("Fatal error: Couldn't handle data receipt from reddit.")
        sys.exit(1)

I hope this snippet will help you correctly design your program. And now that you’ve discovered exceptions, please always remember that exceptions are for handling things that shall stay exceptional. If you throw an exception at some point in one of your programs, always ask yourself if this is something that should happen when something unexpected happens (like a webpage not loading), or if it’s an expected error (like a page loading but giving you an output that is not expected).

Answered By: zmo
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.