如何在发生Traceback错误时让程序继续运行
我写了一个简单的脚本,目的是为了好玩,它会从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 个回答
关于词汇,您遇到的实际错误是一个异常,它是在程序运行过程中因为发现了运行时错误而被抛出的,而追踪信息则是程序线程,它告诉您异常是在哪里被抛出的。
基本上,您需要的是一个异常处理器:
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)
我希望这个代码片段能帮助您正确设计程序。现在您已经了解了异常,请始终记住,异常是用来处理那些应该保持特殊的情况。如果您在程序的某个地方抛出了一个异常,请始终问自己,这是否是因为发生了意外情况(比如网页无法加载),还是这是一个预期中的错误(比如网页加载了但返回了意想不到的结果)。