如何在发生Traceback错误时让程序继续运行

0 投票
1 回答
1102 浏览
提问于 2025-04-18 05:19

我写了一个简单的脚本,目的是为了好玩,它会从http://www.reddit.com/r/random/comments.json?limit=1获取最新的评论,然后通过espeak来朗读。不过我遇到了一个问题。如果Reddit没有给我返回json数据,这种情况经常发生,脚本就会停止运行,并显示错误信息。这就很麻烦,因为脚本会因此中断。有没有什么办法可以在加载失败时重试获取json数据呢?我使用的是requests库,如果这有什么关系的话。

如果你需要,这里是获取json数据的代码部分

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']

1 个回答

4

关于词汇,您遇到的实际错误是一个异常,它是在程序运行过程中因为发现了运行时错误而被抛出的,而追踪信息则是程序线程,它告诉您异常是在哪里被抛出的。

基本上,您需要的是一个异常处理器

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

这样您就可以跳过那些需要无法正常工作的部分。也可以看看这个文档:HandlingExceptions - Python Wiki

正如pss所建议的,如果您想在网址加载失败后重试:

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']

注意:这个解决方案可能不是最优的,因为如果您处于离线状态或者网址总是失败,它会进入无限循环。如果您重试得太快或次数太多,Reddit也可能会封禁您。

注意2:我使用的是最新的Python 3语法来处理异常,这在2.7之前的Python版本中可能无法使用。

注意3:您可能还想选择一个不同于Exception的类来处理异常,以便能够选择您想处理的错误类型。这主要取决于您的应用设计,根据您所说的,您可能想处理requests.exceptions.ConnectionError,但可以查看请求的文档来选择合适的。

以下是您可能想要的,但请仔细考虑并根据您的使用情况进行调整:

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)

我希望这个代码片段能帮助您正确设计程序。现在您已经了解了异常,请始终记住,异常是用来处理那些应该保持特殊的情况。如果您在程序的某个地方抛出了一个异常,请始终问自己,这是否是因为发生了意外情况(比如网页无法加载),还是这是一个预期中的错误(比如网页加载了但返回了意想不到的结果)。

撰写回答